From 8b295b35e877457dd3232f0056d762f377c55b6a Mon Sep 17 00:00:00 2001 From: MateuszOszer <69958773+MateuszOszer@users.noreply.github.com> Date: Mon, 7 Sep 2020 13:29:19 +0200 Subject: [PATCH] Fixes to the Sandbox issue (#204) Fixes to the Sandbox issue Fixes #177 Fixes #202 --- main/}bedrock.cube.data.clear.pro | 1360 +++++++-------- main/}bedrock.cube.data.export.pro | 2540 ++++++++++++++-------------- 2 files changed, 1974 insertions(+), 1926 deletions(-) diff --git a/main/}bedrock.cube.data.clear.pro b/main/}bedrock.cube.data.clear.pro index 15f5c28..664999f 100644 --- a/main/}bedrock.cube.data.clear.pro +++ b/main/}bedrock.cube.data.clear.pro @@ -1,664 +1,696 @@ -601,100 -602,"}bedrock.cube.data.clear" -562,"NULL" -586, -585, -564, -565,"hSSt2wr^a^juzaGhCKzh0>7jEMcD_<9wU@]5SryH7qPIaT\wGsh<64h1yRjvsiLU5`:[b;sdMFbf@UMwfPGO>zqC4DOh7nVllZbBfn>CYgA0;nq\kEBHlS4A7HSgQjVI:NC9dLi\TyhcEwK>oTGV]VfJWwmuQ7?xh601DFxCTB[alXB1x '' ); - If( sDelimDim @= sElementStartDelim % sDelimDim @= sDelimElem % sElementStartDelim @= sDelimElem ); - sMessage = 'The delimiters cannot be the same.'; - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - EndIf; -EndIf; - -# Validate cubelogging parameter -If( pCubeLogging <> 0 & pCubeLogging <> 1 & pCubeLogging <> 2); - sMessage = 'The cube logging parameter incorrect'; - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); -EndIf; - -# If no cube has been specified then terminate process -If( Trim( pCube ) @= '' ); - sMessage = 'No cube(s) specified.'; - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); -EndIf; - -# Validate parallelization filter -If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); - sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); - If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 ); - sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.'; - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - EndIf; -EndIf; - -# Validate Max Threads -If( pParallelThreads >= 1 ); - nMaxThreads = Round(pParallelThreads); -Else; - # Single thread mode - nMaxThreads = 1; -EndIf; - -# Validate Sandbox -If( TRIM( pSandbox ) @<> '' ); - If( ServerSandboxExists( pSandbox ) = 0 ); - SetUseActiveSandboxProperty( 0 ); - nErrors = nErrors + 1; - sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.'); - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - Else; - ServerActiveSandboxSet( pSandbox ); - SetUseActiveSandboxProperty( 1 ); - EndIf; -Else; - SetUseActiveSandboxProperty( 0 ); -EndIf; - -### Check for errors before continuing -If( nErrors <> 0 ); - If( pStrictErrorHandling = 1 ); - ProcessQuit; - Else; - ProcessBreak; - EndIf; -EndIf; - -# Loop through cubes in pCube -sCubes = pCube; -nCubeDelimiterIndex = 1; -# Get 1st cube -While( nCubeDelimiterIndex <> 0 ); - - # Extract 1st cube > sCube - nCubeDelimiterIndex = Scan( pDimDelim, sCubes ); - If( nCubeDelimiterIndex = 0 ); - sCube = sCubes; - Else; - sCube = Trim( SubSt( sCubes, 1, nCubeDelimiterIndex - 1 ) ); - sCubes = Trim( Subst( sCubes, nCubeDelimiterIndex + Long(pDimDelim), Long( sCubes ) ) ); - EndIf; - - bParallel = 0; - - # Check if sCube has wildcard - If( Scan( '*', sCube ) = 0); - # Validate cube - If( CubeExists(sCube) = 0 ); - nErrors = 1; - sMessage = Expand( 'Cube %sCube% does not exist.' ); - LogOutput( 'ERROR', Expand( cMsgErrorContent ) ); - If( pStrictErrorHandling = 1 ); - ProcessQuit; - Else; - ProcessBreak; - EndIf; - Else; - If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); - nDim = 1; - sDim = TABDIM( sCube, nDim); - While ( sDim @<> '' ); - sDim = TABDIM( sCube, nDim); - If ( sDim @= sDimParallel ); - bParallel = 1; - sDim = ''; - EndIf; - nDim = nDim + 1; - End; - EndIf; - If( bParallel = 1 ); - sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); - sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) ); - If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim ); - sElementList = sElementList | pEleDelim; - EndIf; - ## Counting elements in element list - sElementListCount = sElementList; - nElements = 0; - While( Scan( pEleDelim, sElementListCount ) > 0 ); - nElements = nElements + 1; - sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) ); - End; - IF( Mod( nElements, nMaxThreads ) = 0 ); - nElemsPerThread = INT( nElements / nMaxThreads ); - ELSE; - nElemsPerThread = INT( nElements / nMaxThreads ) + 1; - ENDIF; - nThreadElCounter = 0; - While( Scan( pEleDelim, sElementList ) > 0 ); - sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 ); - sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) ); - # Do recursive process call with new RunProcess function - nThreadElCounter = nThreadElCounter + 1; - sDimDelim = If(pFilter @= '', '', pDimDelim ); - IF( nThreadElCounter = 1 ); - sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%'); - ELSE; - sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%'); - ENDIF; - IF( nThreadElCounter >= nElemsPerThread ); - RunProcess( cThisProcName, 'pLogoutput', pLogoutput, - 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, - 'pFilterParallel', '', 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, - 'pEleDelim', pEleDelim, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox - ); - nThreadElCounter = 0; - sFilter = ''; - ENDIF; - End; - ## Process last elements - only when filter is not empty (there are still elements) otherwise the entire cube is emptied - IF( sFilter @<> '' ); - RunProcess( cThisProcName, 'pLogoutput', pLogoutput, - 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, - 'pFilterParallel', '', 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, - 'pEleDelim', pEleDelim, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox - ); - ENDIF; - Else; - ## Validate the View & filter parameter - If( Trim( pView ) @= '' & Trim( pFilter ) @= '' ); - sMessage = Expand('No view OR filter specified so the entire %sCube% cube has been cleared.'); - IF( pLogoutput = 1 ); - LogOutput( 'INFO' , Expand( 'Process:%cThisProcName% Message:%sMessage%' ) ); - ENDIF; - CubeClearData( sCube ); - Else; - # Use different view/subset for different cubes - sTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); - sRandomInt = NumberToString( INT( RAND( ) * 1000 )); - cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' ); - #cTempSub = cDefaultView; - - If( Trim( pView ) @= '' ); - cView = cDefaultView ; - Else; - cView = Trim( pView ); - EndIf; - - # Clear view - If( ViewExists( sCube , cView ) = 0 ); - ## Validate that a Filter has been provided so that a view can be created. - If( Trim( pFilter ) @= '' ); - sMessage = Expand('View %cView% does not exist in the %sCube% cube AND no Filter has not been specified in order to create a view.'); - LogOutput( 'INFO' , Expand( cMsgErrorContent ) ); - #ProcessBreak; - EndIf; - - ### Create View using filter (temp view, therefore no need to destroy) ### - sProc = '}bedrock.cube.view.create'; - nRet = ExecuteProcess( sProc, - 'pLogOutput', pLogOutput, - 'pStrictErrorHandling', pStrictErrorHandling, - 'pCube', sCube, - 'pView', cView, - 'pFilter', pFilter, - 'pSuppressZero', 1, - 'pSuppressConsol',1, - 'pSuppressRules',1, - 'pDimDelim', pDimDelim, - 'pEleStartDelim', pEleStartDelim, - 'pEleDelim', pEleDelim, - 'pTemp', pTemp, - 'pSubN', pSubN - ); - - ### Zero Out View ### - If ( nRet = ProcessExitNormal() ); - If ( pCubeLogging <= 1 ); - sCubeLogging = CellGetS('}CubeProperties', sCube, 'LOGGING' ); - CubeSetLogChanges( sCube, pCubeLogging); - EndIf; - ViewZeroOut( sCube, cView ); - sMessage = Expand( 'Succeeded in creating the %cView% view in the %sCube% cube and data has been cleared.' ); - IF( pLogoutput = 1 ); - LogOutput( 'INFO', Expand( 'Process:%cThisProcName% Message:%sMessage%' ) ); - ENDIF; - If ( pCubeLogging <= 1 ); - CubeSetLogChanges( sCube, IF(sCubeLogging@='YES',1,0) ); - EndIf; - Else; - nErrors = nErrors + 1; - sMessage = Expand( 'Creating view by %sProc% has failed. Nothing has been cleared in the %sCube% cube.' ); - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - EndIf; - Else; - If ( pCubeLogging <= 1 ); - sCubeLogging = CellGetS('}CubeProperties', sCube, 'LOGGING' ); - CubeSetLogChanges( sCube, pCubeLogging); - EndIf; - ViewZeroOut( sCube, cView ); - If ( pCubeLogging <= 1 ); - CubeSetLogChanges( sCube, IF(sCubeLogging@='YES',1,0) ); - EndIf; - Endif; - Endif; - EndIf; - Endif; - Else; - # Create subset of cubes using Wildcard to loop through cubes in pCube with wildcard - sCubeExp = '"'|sCube|'"'; - sMdx = '{TM1FILTERBYPATTERN( {TM1SUBSETALL( [}Cubes] )},'|sCubeExp| ')}'; - If( SubsetExists( '}Cubes' , cTempSub ) = 1 ); - # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times - SubsetMDXSet( '}Cubes' , cTempSub, sMDX ); - Else; - # temp subset, therefore no need to destroy in epilog - SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes' , 1 ); - EndIf; - - # Loop through cubes in subset created based on wildcard - nCountCube = SubsetGetSize( '}Cubes' , cTempSub ); - While( nCountCube >= 1 ); - # Use different view/subset for different cubes - sTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); - sRandomInt = NumberToString( INT( RAND( ) * 1000 )); - cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' ); - sCube = SubsetGetElementName( '}Cubes' , cTempSub, nCountCube ); - # Validate cube name Not necessary as derived from subset of }Cubes - If( CubeExists(sCube) = 0 ); - nErrors = 1; - sMessage = Expand( '%sCube% does not exist.' ); - LogOutput( 'ERROR', Expand( cMsgErrorContent ) ); - Else; - If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); - nDim = 1; - sDim = TABDIM( sCube, nDim); - While ( sDim @<> '' ); - sDim = TABDIM( sCube, nDim); - If ( sDim @= sDimParallel ); - bParallel = 1; - sDim = ''; - EndIf; - nDim = nDim + 1; - End; - EndIf; - If( bParallel = 1 ); - sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); - sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) ); - If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim ); - sElementList = sElementList | pEleDelim; - EndIf; - ## Counting elements in element list - sElementListCount = sElementList; - nElements = 0; - While( Scan( pEleDelim, sElementListCount ) > 0 ); - nElements = nElements + 1; - sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) ); - End; - IF( Mod( nElements, nMaxThreads ) = 0 ); - nElemsPerThread = INT( nElements / nMaxThreads ); - ELSE; - nElemsPerThread = INT( nElements / nMaxThreads ) + 1; - ENDIF; - nThreadElCounter = 0; - While( Scan( pEleDelim, sElementList ) > 0 ); - sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 ); - sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) ); - # Do recursive process call with new RunProcess function - nThreadElCounter = nThreadElCounter + 1; - sDimDelim = If(pFilter @= '', '', pDimDelim ); - IF( nThreadElCounter = 1 ); - sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%'); - ELSE; - sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%'); - ENDIF; - IF( nThreadElCounter >= nElemsPerThread ); - RunProcess( cThisProcName, 'pLogoutput', pLogoutput, - 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, - 'pFilterParallel', '', 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, - 'pEleDelim', pEleDelim, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox - ); - nThreadElCounter = 0; - sFilter = ''; - ENDIF; - End; - ## Process last elements - IF( sFilter @<> '' ); - RunProcess( cThisProcName, 'pLogoutput', pLogoutput, - 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, - 'pFilterParallel', '', 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, - 'pEleDelim', pEleDelim, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox - ); - ENDIF; - Else; - ## Validate the View & filter parameter - If( Trim( pView ) @= '' & Trim( pFilter ) @= '' ); - # Clear entire cube - sMessage = Expand('No view OR filter specified so the entire %sCube% cube has been cleared.'); - IF( pLogoutput = 1 ); - LogOutput( 'INFO' , Expand( 'Process:%cThisProcName% Message:%sMessage%' ) ); - ENDIF; - CubeClearData( sCube ); - Else; - # Clear view cView - If( Trim( pView ) @= '' ); - cView = cDefaultView ; - Else; - cView = Trim( pView ); - EndIf; - - If( ViewExists( sCube, cView ) = 0 ); - ## Validate that a Filter has been provided so that a view can be created. - If( Trim( pFilter ) @= '' ); - sMessage = Expand('View %cView% does not exist for %sCube% AND no Filter has not been specified in order to create a view.'); - LogOutput( 'ERROR' , Expand( cMsgErrorContent ) ); - #ProcessBreak; - EndIf; - - ### Create View using filter (temp view, therefore no need to destroy) ### - sProc = '}bedrock.cube.view.create'; - nRet = ExecuteProcess( sProc, - 'pLogOutput', pLogOutput, - 'pStrictErrorHandling', pStrictErrorHandling, - 'pCube', sCube, - 'pView', cView, - 'pFilter', pFilter, - 'pSuppressZero', 1, - 'pSuppressConsol',1, - 'pSuppressRules',1, - 'pDimDelim', pDimDelim, - 'pEleStartDelim', pEleStartDelim, - 'pEleDelim', pEleDelim, - 'pTemp', pTemp, - 'pSubN', pSubN - ); - - ### Zero Out View ### - IF ( nRet = ProcessExitNormal() ); - If ( pCubeLogging <= 1 ); - sCubeLogging = CellGetS('}CubeProperties', sCube, 'LOGGING' ); - CubeSetLogChanges( sCube, pCubeLogging); - EndIf; - ViewZeroOut( sCube, cView ); - sMessage = Expand( 'Succeeded in creating the %cView% view in the %sCube% cube and data has been cleared.' ); - IF( pLogoutput = 1 ); - LogOutput( 'INFO', Expand( 'Process:%cThisProcName% Message:%sMessage%' ) ); - ENDIF; - If ( pCubeLogging <= 1 ); - CubeSetLogChanges( sCube, IF(sCubeLogging@='YES',1,0) ); - EndIf; - ELSE; - nErrors = nErrors + 1; - sMessage = Expand( 'Creating view by %sProc% has failed. Nothing has been cleared in the %sCube% cube.' ); - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - ENDIF; - Else; - If ( pCubeLogging <= 1 ); - sCubeLogging = CellGetS('}CubeProperties', sCube, 'LOGGING' ); - CubeSetLogChanges( sCube, pCubeLogging); - EndIf; - ViewZeroOut( sCube, cView ); - If ( pCubeLogging <= 1 ); - CubeSetLogChanges( sCube, IF(sCubeLogging@='YES',1,0) ); - EndIf; - Endif; - EndIf; - EndIf; - nCountCube = nCountCube - 1; - # Use different view/subset for different cubes - sTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); - sRandomInt = NumberToString( INT( RAND( ) * 1000 )); - cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' ); - #cTempSub = cDefaultView; - EndIf; - End; - EndIf; -End; - -### End Prolog ### -573,4 - -#****Begin: Generated Statements*** -#****End: Generated Statements**** - -574,4 - -#****Begin: Generated Statements*** -#****End: Generated Statements**** - -575,27 - -#****Begin: Generated Statements*** -#****End: Generated Statements**** - -################################################################################################# -##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## -################################################################################################# - -### Return code & final error message handling -If( nErrors > 0 ); - sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.'; - nProcessReturnCode = 0; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' ); - If( pStrictErrorHandling = 1 ); - ProcessQuit; - EndIf; -Else; - sProcessAction = Expand( 'Process:%cThisProcName% successfully cleared data out of the %pCube% cube(s).' ); - sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' ); - nProcessReturnCode = 1; - If( pLogoutput = 1 ); - LogOutput('INFO', Expand( sProcessAction ) ); - EndIf; -EndIf; - -### End Epilog ### -576,CubeAction=1511 DataAction=1503 CubeLogChanges=0 -930,0 -638,1 -804,0 -1217,1 -900, -901, -902, -938,0 -937, -936, -935, -934, -932,0 -933,0 -903, -906, -929, -907, -908, -904,0 -905,0 -909,0 -911, -912, -913, -914, -915, -916, -917,0 -918,1 -919,0 -920,0 -921,"" -922,"" -923,0 -924,"" -925,"" -926,"" -927,"" +601,100 +602,"}bedrock.cube.data.clear" +562,"NULL" +586, +585, +564, +565,"n:jdhzE<0>X8B>rK@SF\h=cOsF0>aXfW2?obi[NLYl4ptpNoJOl?LLQOSDI:FqOi[iOZ?7EPsEPK>k" +559,1 +928,0 +593, +594, +595, +597, +598, +596, +800, +801, +566,0 +567,"," +588,"." +589,"," +568,"""" +570, +571, +569,0 +592,0 +599,1000 +560,14 +pLogOutput +pStrictErrorHandling +pCube +pView +pFilter +pFilterParallel +pParallelThreads +pDimDelim +pEleStartDelim +pEleDelim +pCubeLogging +pTemp +pSandbox +pSubN +561,14 +1 +1 +2 +2 +2 +2 +1 +2 +2 +2 +1 +1 +2 +1 +590,14 +pLogOutput,0 +pStrictErrorHandling,0 +pCube,"" +pView,"" +pFilter,"" +pFilterParallel,"" +pParallelThreads,0 +pDimDelim,"&" +pEleStartDelim,"¦" +pEleDelim,"+" +pCubeLogging,0 +pTemp,1 +pSandbox,"" +pSubN,0 +637,14 +pLogOutput,"OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)" +pStrictErrorHandling,"OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)" +pCube,"REQUIRED: Cube Name (wildcard * and/or cube1 & cube2 list)" +pView,"OPTIONAL: View name to be cleared (uses pFilter if pView not specified else clears entire cube)" +pFilter,"Optional but ignored if view is specified: Year¦ 2006 + 2007 & Scenario¦ Actual + Budget & Organization¦ North America Operations" +pFilterParallel,"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" +pParallelThreads,"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 )" +pDimDelim,"OPTIONAL: Delimiter for start of Dimension/Element set (default value if blank = '&')" +pEleStartDelim,"OPTIONAL: Delimiter for start of element list (default value if blank = '¦')" +pEleDelim,"OPTIONAL: Delimiter between elements (default value if blank = '+')" +pCubeLogging,"Required: Cube Logging (0 = No transaction logging, 1 = Logging of transactions, 2 = Ignore Cube Logging - No Action Taken)" +pTemp,"OPTIONAL: Make Views and subsets Temporary (1=Temporary)" +pSandbox,"OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)" +pSubN,"OPTIONAL: Create N level subset for all dims not mentioned in pFilter" +577,0 +578,0 +579,0 +580,0 +581,0 +582,0 +603,0 +572,523 +#Region CallThisProcess +# 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. +If( 1 = 0 ); + ExecuteProcess( '}bedrock.cube.data.clear', 'pLogOutput', pLogOutput, + 'pStrictErrorHandling', pStrictErrorHandling, + 'pCube', '', 'pView', '', 'pFilter', '', + 'pFilterParallel', '', 'pParallelThreads', 0, + 'pDimDelim', '&', 'pEleStartDelim', '¦', 'pEleDelim', '+', + 'pCubeLogging', 0, 'pTemp', 1, 'pSandbox', pSandbox, 'pSubN', 0 + ); +EndIf; +#EndRegion CallThisProcess + +#****Begin: Generated Statements*** +#****End: Generated Statements**** + +################################################################################################# +##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## +################################################################################################# + +#Region @DOC +# Description: +# 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. + +# Use case: Primarily for production systems. +# 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. +# 2/ During development/prototyping can be run manually to clear out a portion of a cube. + +# Note: +# Wildcards can be used or a list of cubes specified to clear data out of multiple cubes simultaneouly. +# If no cube (pCube) or an invalid cube is specified, the process will abort. +# CAUTION: If no view (pView) or filter (pFilter) is specified, the entire cube(s) will be cleared out. +# If a valid view is specified the process will simply zero out that view and ignore any filter (pFilter) specified. +# If no valid view is specified then a temporary view will be built using the filter and its data deleted. +# The filter can handle specific element references for any number of dimensions and elements. +# - The pFilter parameter contains the dimension and elements to be used for filtering. +# - The dimension parameters do not need to be given in the index order of dimensions in the cube. +# - The dimension name is specified as the first member of the delimited string of elements. +# If using the pFilterParallel parameter the **single dimension** used as the "parallelization slicer" cannot appear in +# the pFilter parameters. +# When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time +# and passed to a recursive call of the process being added to pFilter. +#EndRegion @DOC + +### Global Variables +StringGlobalVariable('sProcessReturnCode'); +NumericGlobalVariable('nProcessReturnCode'); +nProcessReturnCode= 0; + +### Constants ### +cThisProcName = GetProcessName(); +cUserName = TM1User(); +cMsgErrorLevel = 'ERROR'; +cMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%'; +cLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pCubeLogging:%pCubeLogging%, pTemp:%pTemp%, pSandbox:%pSandbox%'; +cTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); +cRandomInt = NumberToString( INT( RAND( ) * 1000 )); +cDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' ); +cTempSub = cDefaultView | '_Temp'; + +## LogOutput parameters +IF( pLogoutput = 1 ); + LogOutput('INFO', Expand( cLogInfo ) ); +ENDIF; + +# Trim delimiters +sDelimDim = TRIM(pDimDelim); +sElementStartDelim = TRIM(pEleStartDelim); +sDelimElem = TRIM(pEleDelim); + +### Validate Parameters ### +nErrors = 0; + +## Default filter delimiters +If( pDimDelim @= '' ); + pDimDelim = '&'; +EndIf; +If( pEleStartDelim@= '' ); + pEleStartDelim= '¦'; +EndIf; +If( pEleDelim @= '' ); + pEleDelim = '+'; +EndIf; + +# Check the delimiters +If( Trim( pFilter ) @<> '' ); + If( sDelimDim @= sElementStartDelim % sDelimDim @= sDelimElem % sElementStartDelim @= sDelimElem ); + sMessage = 'The delimiters cannot be the same.'; + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + EndIf; +EndIf; + +# Validate cubelogging parameter +If( pCubeLogging <> 0 & pCubeLogging <> 1 & pCubeLogging <> 2); + sMessage = 'The cube logging parameter incorrect'; + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); +EndIf; + +# If no cube has been specified then terminate process +If( Trim( pCube ) @= '' ); + sMessage = 'No cube(s) specified.'; + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); +EndIf; + +# Validate parallelization filter +If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); + sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); + If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 ); + sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.'; + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + EndIf; +EndIf; + +# Validate Max Threads +If( pParallelThreads >= 1 ); + nMaxThreads = Round(pParallelThreads); +Else; + # Single thread mode + nMaxThreads = 1; +EndIf; + +# Validate Sandbox +If( TRIM( pSandbox ) @<> '' ); + If( ServerSandboxExists( pSandbox ) = 0 ); + SetUseActiveSandboxProperty( 0 ); + nErrors = nErrors + 1; + sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.'); + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + Else; + ServerActiveSandboxSet( pSandbox ); + SetUseActiveSandboxProperty( 1 ); + EndIf; +Else; + SetUseActiveSandboxProperty( 0 ); +EndIf; + +### Check for errors before continuing +If( nErrors <> 0 ); + If( pStrictErrorHandling = 1 ); + ProcessQuit; + Else; + ProcessBreak; + EndIf; +EndIf; + +# Loop through cubes in pCube +sCubes = pCube; +nCubeDelimiterIndex = 1; +# Get 1st cube +While( nCubeDelimiterIndex <> 0 ); + + # Extract 1st cube > sCube + nCubeDelimiterIndex = Scan( pDimDelim, sCubes ); + If( nCubeDelimiterIndex = 0 ); + sCube = sCubes; + Else; + sCube = Trim( SubSt( sCubes, 1, nCubeDelimiterIndex - 1 ) ); + sCubes = Trim( Subst( sCubes, nCubeDelimiterIndex + Long(pDimDelim), Long( sCubes ) ) ); + EndIf; + + bParallel = 0; + + # Check if sCube has wildcard + If( Scan( '*', sCube ) = 0); + # Validate cube + If( CubeExists(sCube) = 0 ); + nErrors = 1; + sMessage = Expand( 'Cube %sCube% does not exist.' ); + LogOutput( 'ERROR', Expand( cMsgErrorContent ) ); + If( pStrictErrorHandling = 1 ); + ProcessQuit; + Else; + ProcessBreak; + EndIf; + Else; + If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); + nDim = 1; + sDim = TABDIM( sCube, nDim); + While ( sDim @<> '' ); + sDim = TABDIM( sCube, nDim); + If ( sDim @= sDimParallel ); + bParallel = 1; + sDim = ''; + EndIf; + nDim = nDim + 1; + End; + EndIf; + If( bParallel = 1 ); + sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); + sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) ); + If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim ); + sElementList = sElementList | pEleDelim; + EndIf; + ## Counting elements in element list + sElementListCount = sElementList; + nElements = 0; + While( Scan( pEleDelim, sElementListCount ) > 0 ); + nElements = nElements + 1; + sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) ); + End; + IF( Mod( nElements, nMaxThreads ) = 0 ); + nElemsPerThread = INT( nElements / nMaxThreads ); + ELSE; + nElemsPerThread = INT( nElements / nMaxThreads ) + 1; + ENDIF; + nThreadElCounter = 0; + While( Scan( pEleDelim, sElementList ) > 0 ); + sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 ); + sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) ); + # Do recursive process call with new RunProcess function + nThreadElCounter = nThreadElCounter + 1; + sDimDelim = If(pFilter @= '', '', pDimDelim ); + IF( nThreadElCounter = 1 ); + sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%'); + ELSE; + sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%'); + ENDIF; + IF( nThreadElCounter >= nElemsPerThread ); + RunProcess( cThisProcName, 'pLogoutput', pLogoutput, + 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, + 'pFilterParallel', '', 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, + 'pEleDelim', pEleDelim, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox + ); + nThreadElCounter = 0; + sFilter = ''; + ENDIF; + End; + ## Process last elements - only when filter is not empty (there are still elements) otherwise the entire cube is emptied + IF( sFilter @<> '' ); + RunProcess( cThisProcName, 'pLogoutput', pLogoutput, + 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, + 'pFilterParallel', '', 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, + 'pEleDelim', pEleDelim, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox + ); + ENDIF; + Else; + ## Validate the View & filter parameter + If( Trim( pView ) @= '' & Trim( pFilter ) @= '' & Trim( pSandbox ) @= '' ); + sMessage = Expand('No view OR filter specified so the entire %sCube% cube has been cleared.'); + IF( pLogoutput = 1 ); + LogOutput( 'INFO' , Expand( 'Process:%cThisProcName% Message:%sMessage%' ) ); + ENDIF; + CubeClearData( sCube ); + Else; + # Use different view/subset for different cubes + sTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); + sRandomInt = NumberToString( INT( RAND( ) * 1000 )); + cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' ); + #cTempSub = cDefaultView; + + If( Trim( pView ) @= '' ); + cView = cDefaultView ; + Else; + cView = Trim( pView ); + EndIf; + + # Clear view + If( ViewExists( sCube , cView ) = 0 ); + ## Validate that a Filter has been provided so that a view can be created. + If( Trim( pFilter ) @= '' ); + sMessage = Expand('View %cView% does not exist in the %sCube% cube AND no Filter has not been specified in order to create a view.'); + LogOutput( 'INFO' , Expand( cMsgErrorContent ) ); + #ProcessBreak; + EndIf; + + ### Create View using filter (temp view, therefore no need to destroy) ### + sProc = '}bedrock.cube.view.create'; + nRet = ExecuteProcess( sProc, + 'pLogOutput', pLogOutput, + 'pStrictErrorHandling', pStrictErrorHandling, + 'pCube', sCube, + 'pView', cView, + 'pFilter', pFilter, + 'pSuppressZero', 1, + 'pSuppressConsol',1, + 'pSuppressRules',1, + 'pDimDelim', pDimDelim, + 'pEleStartDelim', pEleStartDelim, + 'pEleDelim', pEleDelim, + 'pTemp', pTemp, + 'pSubN', pSubN + ); + + + # Validate Sandbox + If( TRIM( pSandbox ) @<> '' ); + If( ServerSandboxExists( pSandbox ) = 0 ); + SetUseActiveSandboxProperty( 0 ); + nErrors = nErrors + 1; + sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.'); + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + Else; + ServerActiveSandboxSet( pSandbox ); + SetUseActiveSandboxProperty( 1 ); + EndIf; + Else; + SetUseActiveSandboxProperty( 0 ); + EndIf; + + ### Zero Out View ### + If ( nRet = ProcessExitNormal() ); + If ( pCubeLogging <= 1 ); + sCubeLogging = CellGetS('}CubeProperties', sCube, 'LOGGING' ); + CubeSetLogChanges( sCube, pCubeLogging); + EndIf; + ViewZeroOut( sCube, cView ); + sMessage = Expand( 'Succeeded in creating the %cView% view in the %sCube% cube and data has been cleared.' ); + IF( pLogoutput = 1 ); + LogOutput( 'INFO', Expand( 'Process:%cThisProcName% Message:%sMessage%' ) ); + ENDIF; + If ( pCubeLogging <= 1 ); + CubeSetLogChanges( sCube, IF(sCubeLogging@='YES',1,0) ); + EndIf; + Else; + nErrors = nErrors + 1; + sMessage = Expand( 'Creating view by %sProc% has failed. Nothing has been cleared in the %sCube% cube.' ); + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + EndIf; + Else; + If ( pCubeLogging <= 1 ); + sCubeLogging = CellGetS('}CubeProperties', sCube, 'LOGGING' ); + CubeSetLogChanges( sCube, pCubeLogging); + EndIf; + ViewZeroOut( sCube, cView ); + If ( pCubeLogging <= 1 ); + CubeSetLogChanges( sCube, IF(sCubeLogging@='YES',1,0) ); + EndIf; + Endif; + Endif; + EndIf; + Endif; + Else; + # Create subset of cubes using Wildcard to loop through cubes in pCube with wildcard + sCubeExp = '"'|sCube|'"'; + sMdx = '{TM1FILTERBYPATTERN( {TM1SUBSETALL( [}Cubes] )},'|sCubeExp| ')}'; + If( SubsetExists( '}Cubes' , cTempSub ) = 1 ); + # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times + SubsetMDXSet( '}Cubes' , cTempSub, sMDX ); + Else; + # temp subset, therefore no need to destroy in epilog + SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes' , 1 ); + EndIf; + + # Loop through cubes in subset created based on wildcard + nCountCube = SubsetGetSize( '}Cubes' , cTempSub ); + While( nCountCube >= 1 ); + # Use different view/subset for different cubes + sTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); + sRandomInt = NumberToString( INT( RAND( ) * 1000 )); + cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' ); + sCube = SubsetGetElementName( '}Cubes' , cTempSub, nCountCube ); + # Validate cube name Not necessary as derived from subset of }Cubes + If( CubeExists(sCube) = 0 ); + nErrors = 1; + sMessage = Expand( '%sCube% does not exist.' ); + LogOutput( 'ERROR', Expand( cMsgErrorContent ) ); + Else; + If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); + nDim = 1; + sDim = TABDIM( sCube, nDim); + While ( sDim @<> '' ); + sDim = TABDIM( sCube, nDim); + If ( sDim @= sDimParallel ); + bParallel = 1; + sDim = ''; + EndIf; + nDim = nDim + 1; + End; + EndIf; + If( bParallel = 1 ); + sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); + sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) ); + If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim ); + sElementList = sElementList | pEleDelim; + EndIf; + ## Counting elements in element list + sElementListCount = sElementList; + nElements = 0; + While( Scan( pEleDelim, sElementListCount ) > 0 ); + nElements = nElements + 1; + sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) ); + End; + IF( Mod( nElements, nMaxThreads ) = 0 ); + nElemsPerThread = INT( nElements / nMaxThreads ); + ELSE; + nElemsPerThread = INT( nElements / nMaxThreads ) + 1; + ENDIF; + nThreadElCounter = 0; + While( Scan( pEleDelim, sElementList ) > 0 ); + sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 ); + sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) ); + # Do recursive process call with new RunProcess function + nThreadElCounter = nThreadElCounter + 1; + sDimDelim = If(pFilter @= '', '', pDimDelim ); + IF( nThreadElCounter = 1 ); + sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%'); + ELSE; + sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%'); + ENDIF; + IF( nThreadElCounter >= nElemsPerThread ); + RunProcess( cThisProcName, 'pLogoutput', pLogoutput, + 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, + 'pFilterParallel', '', 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, + 'pEleDelim', pEleDelim, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox + ); + nThreadElCounter = 0; + sFilter = ''; + ENDIF; + End; + ## Process last elements + IF( sFilter @<> '' ); + RunProcess( cThisProcName, 'pLogoutput', pLogoutput, + 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, + 'pFilterParallel', '', 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, + 'pEleDelim', pEleDelim, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox + ); + ENDIF; + Else; + ## Validate the View & filter parameter + If( Trim( pView ) @= '' & Trim( pFilter ) @= '' & Trim( pSandbox ) @= '' ); + # Clear entire cube + sMessage = Expand('No view OR filter specified so the entire %sCube% cube has been cleared.'); + IF( pLogoutput = 1 ); + LogOutput( 'INFO' , Expand( 'Process:%cThisProcName% Message:%sMessage%' ) ); + ENDIF; + CubeClearData( sCube ); + Else; + # Clear view cView + If( Trim( pView ) @= '' ); + cView = cDefaultView ; + Else; + cView = Trim( pView ); + EndIf; + + If( ViewExists( sCube, cView ) = 0 ); + ## Validate that a Filter has been provided so that a view can be created. + If( Trim( pFilter ) @= '' ); + sMessage = Expand('View %cView% does not exist for %sCube% AND no Filter has not been specified in order to create a view.'); + LogOutput( 'ERROR' , Expand( cMsgErrorContent ) ); + #ProcessBreak; + EndIf; + + ### Create View using filter (temp view, therefore no need to destroy) ### + sProc = '}bedrock.cube.view.create'; + nRet = ExecuteProcess( sProc, + 'pLogOutput', pLogOutput, + 'pStrictErrorHandling', pStrictErrorHandling, + 'pCube', sCube, + 'pView', cView, + 'pFilter', pFilter, + 'pSuppressZero', 1, + 'pSuppressConsol',1, + 'pSuppressRules',1, + 'pDimDelim', pDimDelim, + 'pEleStartDelim', pEleStartDelim, + 'pEleDelim', pEleDelim, + 'pTemp', pTemp, + 'pSubN', pSubN + ); + + # Validate Sandbox + If( TRIM( pSandbox ) @<> '' ); + If( ServerSandboxExists( pSandbox ) = 0 ); + SetUseActiveSandboxProperty( 0 ); + nErrors = nErrors + 1; + sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.'); + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + Else; + ServerActiveSandboxSet( pSandbox ); + SetUseActiveSandboxProperty( 1 ); + EndIf; + Else; + SetUseActiveSandboxProperty( 0 ); + EndIf; + + + ### Zero Out View ### + IF ( nRet = ProcessExitNormal() ); + If ( pCubeLogging <= 1 ); + sCubeLogging = CellGetS('}CubeProperties', sCube, 'LOGGING' ); + CubeSetLogChanges( sCube, pCubeLogging); + EndIf; + ViewZeroOut( sCube, cView ); + sMessage = Expand( 'Succeeded in creating the %cView% view in the %sCube% cube and data has been cleared.' ); + IF( pLogoutput = 1 ); + LogOutput( 'INFO', Expand( 'Process:%cThisProcName% Message:%sMessage%' ) ); + ENDIF; + If ( pCubeLogging <= 1 ); + CubeSetLogChanges( sCube, IF(sCubeLogging@='YES',1,0) ); + EndIf; + ELSE; + nErrors = nErrors + 1; + sMessage = Expand( 'Creating view by %sProc% has failed. Nothing has been cleared in the %sCube% cube.' ); + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + ENDIF; + Else; + If ( pCubeLogging <= 1 ); + sCubeLogging = CellGetS('}CubeProperties', sCube, 'LOGGING' ); + CubeSetLogChanges( sCube, pCubeLogging); + EndIf; + ViewZeroOut( sCube, cView ); + If ( pCubeLogging <= 1 ); + CubeSetLogChanges( sCube, IF(sCubeLogging@='YES',1,0) ); + EndIf; + Endif; + EndIf; + EndIf; + nCountCube = nCountCube - 1; + # Use different view/subset for different cubes + sTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); + sRandomInt = NumberToString( INT( RAND( ) * 1000 )); + cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' ); + #cTempSub = cDefaultView; + EndIf; + End; + EndIf; +End; + +### End Prolog ### +573,4 + +#****Begin: Generated Statements*** +#****End: Generated Statements**** + +574,4 + +#****Begin: Generated Statements*** +#****End: Generated Statements**** + +575,27 + +#****Begin: Generated Statements*** +#****End: Generated Statements**** + +################################################################################################# +##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## +################################################################################################# + +### Return code & final error message handling +If( nErrors > 0 ); + sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.'; + nProcessReturnCode = 0; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' ); + If( pStrictErrorHandling = 1 ); + ProcessQuit; + EndIf; +Else; + sProcessAction = Expand( 'Process:%cThisProcName% successfully cleared data out of the %pCube% cube(s).' ); + sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' ); + nProcessReturnCode = 1; + If( pLogoutput = 1 ); + LogOutput('INFO', Expand( sProcessAction ) ); + EndIf; +EndIf; + +### End Epilog ### +576,CubeAction=1511 DataAction=1503 CubeLogChanges=0 +930,0 +638,1 +804,0 +1217,1 +900, +901, +902, +938,0 +937, +936, +935, +934, +932,0 +933,0 +903, +906, +929, +907, +908, +904,0 +905,0 +909,0 +911, +912, +913, +914, +915, +916, +917,0 +918,1 +919,0 +920,0 +921,"" +922,"" +923,0 +924,"" +925,"" +926,"" +927,"" diff --git a/main/}bedrock.cube.data.export.pro b/main/}bedrock.cube.data.export.pro index f5c465b..a530d8d 100644 --- a/main/}bedrock.cube.data.export.pro +++ b/main/}bedrock.cube.data.export.pro @@ -1,1262 +1,1278 @@ -601,100 -602,"}bedrock.cube.data.export" -562,"VIEW" -586,"}APQ Staging TempSource" -585,"}APQ Staging TempSource" -564, -565,"d>kMa8gbG6tYMSVC[5CBJGvJq379taBg8c27\L6E5awJ8D@lHpeaYOyiM6v`ZrTtng2YW3:>mbQ8EmbsHC:tDt9`;8_L3Pz3C^c1vVSLXE7NBGqDlRd5uv^25qdmyxjeVRgCG`p9" -559,1 -928,0 -593, -594, -595, -597, -598, -596, -800, -801, -566,0 -567,"," -588,"." -589,"," -568,"""" -570,}TI_Dummy_View -571, -569,0 -592,0 -599,1000 -560,25 -pLogoutput -pStrictErrorHandling -pCube -pView -pFilter -pFilterParallel -pParallelThreads -pDimDelim -pEleStartDelim -pEleDelim -pSuppressZero -pSuppressConsol -pSuppressRules -pSuppressConsolStrings -pZeroSource -pCubeLogging -pTemp -pFilePath -pFileName -pDelim -pQuote -pTitleRecord -pSandbox -pSubN -pCharacterSet -561,25 -1 -1 -2 -2 -2 -2 -1 -2 -2 -2 -1 -1 -1 -1 -1 -1 -1 -2 -2 -2 -2 -1 -2 -1 -2 -590,25 -pLogoutput,0 -pStrictErrorHandling,0 -pCube,"" -pView,"" -pFilter,"" -pFilterParallel,"" -pParallelThreads,0 -pDimDelim,"&" -pEleStartDelim,"¦" -pEleDelim,"+" -pSuppressZero,1 -pSuppressConsol,1 -pSuppressRules,1 -pSuppressConsolStrings,0 -pZeroSource,0 -pCubeLogging,0 -pTemp,1 -pFilePath,"" -pFileName,"" -pDelim,"," -pQuote,"""" -pTitleRecord,1 -pSandbox,"" -pSubN,0 -pCharacterSet,"" -637,25 -pLogoutput,"OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)" -pStrictErrorHandling,"OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)" -pCube,"REQUIRED: Cube name" -pView,"OPTIONAL: Temporary view name" -pFilter,"OPTIONAL: Filter: Year¦ 2006 + 2007 & Scenario¦ Actual + Budget & Organization¦ North America Operations (Blank=whole cube)" -pFilterParallel,"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" -pParallelThreads,"OPTIONAL: Maximum number of threads to run when parallel processing is enabled ( if <2 will execute one thread, but parallel filter is still applied )" -pDimDelim,"OPTIONAL: Delimiter between dimensions (default value if blank = '&')" -pEleStartDelim,"OPTIONAL: Delimiter for start of element list (default value if blank = '¦')" -pEleDelim,"OPTIONAL: Delimiter between elements (default value if blank = '+')" -pSuppressZero,"OPTIONAL: Suppress Zero Values (1=Suppress)" -pSuppressConsol,"OPTIONAL: Suppress Consolidated Values? (1=Suppress)" -pSuppressRules,"OPTIONAL: Suppress Rule Values? (1=Suppress)" -pSuppressConsolStrings,"OPTIONAL: Suppress Strings on Consolidations (Skip = 1) (Default = 0)" -pZeroSource,"OPTIONAL: Zero Out view AFTER Copy? (Boolean 1=True)" -pCubeLogging,"Required: Cube Logging (0 = No transaction logging, 1 = Logging of transactions, 2 = Ignore Cube Logging - No Action Taken)" -pTemp,"OPTIONAL: Retain temporary view and Subset ( 0 = retain View and Subsets 1 = use temp objects)" -pFilePath,"OPTIONAL: Export Directory (will default to error file path)" -pFileName,"OPTIONAL: Export Filename (If Left Blank Defaults to cube_export.csv)" -pDelim,"OPTIONAL: AsciiOutput delimiter character (Default=comma, exactly 3 digits = ASCII code)" -pQuote,"OPTIONAL: AsciiOutput quote character (Accepts empty quote, exactly 3 digits = ASCII code)" -pTitleRecord,"OPTIONAL: Include Title Record in Export File? (Boolean 0=false, 1=true, 2=title and filter line Default=1)" -pSandbox,"OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)" -pSubN,"OPTIONAL: Create N level subset for all dims not mentioned in pFilter" -pCharacterSet,"OPTIONAL: The output character set (defaults to TM1CS_UTF8 if blank)" -577,101 -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 -V28 -V29 -V30 -V31 -V32 -V33 -V34 -V35 -V36 -V37 -V38 -V39 -V40 -V41 -V42 -V43 -V44 -V45 -V46 -V47 -V48 -V49 -V50 -V51 -V52 -V53 -V54 -V55 -V56 -V57 -V58 -V59 -V60 -V61 -V62 -V63 -V64 -V65 -V66 -V67 -V68 -V69 -V70 -V71 -V72 -V73 -V74 -V75 -V76 -V77 -V78 -V79 -V80 -V81 -V82 -V83 -V84 -V85 -V86 -V87 -V88 -V89 -V90 -V91 -V92 -V93 -V94 -V95 -V96 -V97 -V98 -V99 -V100 -Value -578,101 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -2 -579,101 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -580,101 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -581,101 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -582,101 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -VarType=32 ColType=827 -603,0 -572,379 -#Region CallThisProcess -# 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. -If( 1 = 0 ); - ExecuteProcess( '}bedrock.cube.data.export', 'pLogoutput', pLogoutput, - 'pStrictErrorHandling', pStrictErrorHandling, - 'pCube', '', 'pView', '', 'pFilter', '', - 'pFilterParallel', '', 'pParallelThreads', 0, - 'pDimDelim', '&', 'pEleStartDelim', '¦', 'pEleDelim', '+', - 'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', 1, - 'pZeroSource', 0, 'pCubeLogging', 0, 'pTemp', 1, - 'pFilePath', '', 'pFileName', '', - 'pDelim', ',', 'pQuote', '"', 'pTitleRecord', 1, 'pSandbox', pSandbox, 'pSubN', pSubN - ); -EndIf; -#EndRegion CallThisProcess - -#****Begin: Generated Statements*** -#****End: Generated Statements**** - -################################################################################################# -##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## -################################################################################################# - -#Region @DOC -# Description: -# This TI is designed to export data in a given cube to a flat file for a given "slice" (any dimension/element combination). -# -# Use case: Intended for development/prototyping or in Production environment. -# 1. Export data for import into another TM1 model to eliminate possibility of locking. -# 2. Export data for import into ERP system. -# -# Note: -# * Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort. -# * All other parameters are optional, however, the filter (pFilter) should be specified to limit the size of the file. -# * The default output path is the same as the error file path. -# * As this TI has a view as a data source it requires the implicit variables NValue, SValue and Value_is_String -# * To edit this TI in Architect a tmp cube with minimum 24 dims is needed as the preview data source or set the data -# source to ASCII and manually edit the TI in notepad after saving to add back the required implicit view variables -# * If using the pFilterParallel parameter the **single dimension** used as the "parallelization slicer" cannot appear in -# the pFilter parameter -# * When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time -# and passed to a recursive call of the process being added to pFilter. Each element name will also be appended to the filename -# -# Warning: -# As the *RunProcess* function currently has no mechanism to check for the state of the called process if more processes are -# released than available CPU cores on the server then this could lead to TM1 consuming all available server resources and a -# associated performance issue. Be careful that the number of slicer elements listed in pFilterParallel should not exceed the -# number of available cores. -#EndRegion @DOC - -##Global Variables -StringGlobalVariable('sProcessReturnCode'); -NumericGlobalVariable('nProcessReturnCode'); -StringGlobalVariable('sBedrockViewCreateParsedFilter'); - -### Constants ### -cThisProcName = GetProcessName(); -cUserName = TM1User(); -cTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); -cRandomInt = NumberToString( INT( RAND( ) * 1000 )); -cMsgErrorLevel = 'ERROR'; -cMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%'; -cLogInfo = '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%.'; -cDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' ); -cLenASCIICode = 3; - -pFieldDelim = TRIM(pDelim); -pDimDelim = TRIM(pDimDelim); -pEleStartDelim = TRIM(pEleStartDelim); -pEleDelim = TRIM(pEleDelim); -nDataCount = 0; -nErrors = 0; - -## Default filter delimiters -If( pDimDelim @= '' ); - pDimDelim = '&'; -EndIf; -If( pEleStartDelim@= '' ); - pEleStartDelim= '¦'; -EndIf; -If( pEleDelim @= '' ); - pEleDelim = '+'; -EndIf; -sDelimDim = pDimDelim; -sElementStartDelim = pEleStartDelim; -sDelimelem = pEleDelim; - -## LogOutput parameters -IF( pLogoutput = 1 ); - LogOutput('INFO', Expand( cLogInfo ) ); -ENDIF; - -### Validate Parameters ### - -# If no cube has been specified then terminate process -If( Trim( pCube ) @= '' ); - sMessage = 'No cube specified.'; - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); -ElseIf( CubeExists( pCube ) = 0 ); - sMessage = Expand( 'Cube: %pCube% does not exist.' ); - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); -EndIf; - -## Validate the View parameter -If( TRIM(pView) @= '' ); - cView = cDefaultView ; -Else ; - cView = pView ; -EndIf; -cSubset = cView; - -## check operating system -If( Scan('/', GetProcessErrorFileDirectory)>0); -# sOS = 'Linux'; - sOSDelim = '/'; -Else; -# sOS = 'Windows'; - sOSDelim = '\'; -EndIf; - -# Validate file path -If(Trim( pFilePath ) @= '' ); - pFilePath = GetProcessErrorFileDirectory; -Else; - If( SubSt( pFilePath, Long( pFilePath ), 1 ) @= sOSDelim ); - pFilePath = SubSt( pFilePath, 1, Long( pFilePath ) -1 ); - EndIf; - If( FileExists( pFilePath ) = 0 ); - sMessage = Expand('Invalid export directory: %pFilePath%'); - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - EndIf; - pFilePath = pFilePath | sOSDelim; -EndIf; - -# Validate file name -If( pFileName @= '' ); - sBaseFileName = Expand('%pCube%_Export'); - sExt = '.csv'; - pFileName = sBaseFileName | '.csv'; -Else; - # determine file extension. If no file extension entered then use .csv as default - If( Scan( '.', pFileName ) = 0 ); - sExt = '.csv'; - sBaseFileName = pFileName; - Else; - sExt = SubSt( pFileName, Scan( '.', pFileName ), Long( pFileName ) ); - sBaseFileName = SubSt( pFileName, 1, Scan( '.', pFileName ) - 1 ); - EndIf; - pFileName = sBaseFileName | sExt; -EndIf; -cExportFile = pFilePath | pFileName; - -# Validate parallelization filter -If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); - sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); - If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 ); - sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.'; - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - EndIf; -EndIf; - -# Validate Max Threads -If( pParallelThreads > 0 ); - nMaxThreads = pParallelThreads; -Else; - nMaxThreads = 1; -EndIf; - -# Validate file delimiter & quote character -If( pFieldDelim @= '' ); - pFieldDelim = ','; -Else; - # If length of pFieldDelim is exactly 3 chars and each of them is decimal digit, then the pFieldDelim is entered as ASCII code - nValid = 0; - If ( LONG(pFieldDelim) = cLenASCIICode ); - nChar = 1; - While ( nChar <= cLenASCIICode ); - If( CODE( pFieldDelim, nChar ) >= CODE( '0', 1 ) & CODE( pFieldDelim, nChar ) <= CODE( '9', 1 ) ); - nValid = 1; - Else; - nValid = 0; - EndIf; - nChar = nChar + 1; - End; - EndIf; - If ( nValid<>0 ); - pFieldDelim=CHAR(StringToNumber( pFieldDelim )); - Else; - pFieldDelim = SubSt( Trim( pFieldDelim ), 1, 1 ); - EndIf; -EndIf; -If( pQuote @= '' ); - ## Use no quote character -Else; - # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code - nValid = 0; - If ( LONG(pQuote) = cLenASCIICode ); - nChar = 1; - While ( nChar <= cLenASCIICode ); - If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) ); - nValid = 1; - Else; - nValid = 0; - EndIf; - nChar = nChar + 1; - End; - EndIf; - If ( nValid<>0 ); - pQuote=CHAR(StringToNumber( pQuote )); - Else; - pQuote = SubSt( Trim( pQuote ), 1, 1 ); - EndIf; -EndIf; - -# Validate Sandbox -If( TRIM( pSandbox ) @<> '' ); - If( ServerSandboxExists( pSandbox ) = 0 ); - SetUseActiveSandboxProperty( 0 ); - nErrors = nErrors + 1; - sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.'); - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - Else; - ServerActiveSandboxSet( pSandbox ); - SetUseActiveSandboxProperty( 1 ); - EndIf; -Else; - SetUseActiveSandboxProperty( 0 ); -EndIf; - -# Validate Character Set -If(Trim( pCharacterSet ) @= '' ); - pCharacterSet = 'TM1CS_UTF8'; -EndIf; - -# Jump to Epilog if any errors so far -IF ( nErrors > 0 ); - DataSourceType = 'NULL'; - If( pStrictErrorHandling = 1 ); - ProcessQuit; - Else; - ProcessBreak; - EndIf; -ENDIF; - -# Branch depending on whether to do recursive calls to self on independent threads or run all in this thread -If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); - sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); - sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) ); - If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim ); - sElementList = sElementList | pEleDelim; - EndIf; - ## Counting elements in element list - sElementListCount = sElementList; - nElements = 0; - While( Scan( pEleDelim, sElementListCount ) > 0 ); - nElements = nElements + 1; - sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) ); - End; - IF( Mod( nElements, nMaxThreads ) = 0 ); - nElemsPerThread = INT( nElements / nMaxThreads ); - ELSE; - nElemsPerThread = INT( nElements / nMaxThreads ) + 1; - ENDIF; - nThreadElCounter = 0; - While( Scan( pEleDelim, sElementList ) > 0 ); - sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 ); - sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) ); - # Do recursive process call with new RunProcess function - nThreadElCounter = nThreadElCounter + 1; - sDimDelim = If(pFilter @= '', '', pDimDelim ); - IF( nThreadElCounter = 1 ); - sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%'); - sFileName = Expand('%sBaseFileName%_%sDimParallel%_%sSlicerEle%'); - ELSE; - sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%'); - sFileName = Expand('%sFileName%+%sSlicerEle%'); - ENDIF; - IF( nThreadElCounter >= nElemsPerThread ); - sFileName = Expand('%sFileName%%sExt%'); - RunProcess( cThisProcName, 'pLogoutput', pLogoutput, - 'pCube', pCube, 'pView', '', - 'pFilter', sFilter, 'pFilterParallel', '', - 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, - 'pSuppressZero', pSuppressZero, 'pSuppressConsol', pSuppressConsol, 'pSuppressRules', pSuppressRules, - 'pZeroSource', pZeroSource, 'pCubeLogging', pCubeLogging, - 'pTemp', pTemp, 'pFilePath', pFilePath, 'pFileName', sFileName, - 'pDelim', pFieldDelim, 'pQuote', pQuote, 'pTitleRecord', pTitleRecord, 'pSandbox', pSandbox, 'pSuppressConsolStrings', pSuppressConsolStrings - ); - nThreadElCounter = 0; - sFilter = ''; - sFileName = ''; - ENDIF; - End; - ## Process last elements - only when filter is not empty (there are still elements) - IF( sFilter @<> '' ); - sFileName = Expand('%sFileName%%sExt%'); - RunProcess( cThisProcName, 'pLogoutput', pLogoutput, - 'pCube', pCube, 'pView', '', - 'pFilter', sFilter, 'pFilterParallel', '', - 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, - 'pSuppressZero', pSuppressZero, 'pSuppressConsol', pSuppressConsol, 'pSuppressRules', pSuppressRules, - 'pZeroSource', pZeroSource, 'pCubeLogging', pCubeLogging, - 'pTemp', pTemp, 'pFilePath', pFilePath, 'pFileName', sFileName, - 'pDelim', pFieldDelim, 'pQuote', pQuote, 'pTitleRecord', pTitleRecord, 'pSandbox', pSandbox, 'pSuppressConsolStrings', pSuppressConsolStrings - ); - ENDIF; - DataSourceType = 'NULL'; - nParallelRun = 1; -Else; - # No parallelization is being used. Proceed as normal and do everything internally - - # Determine number of dims in source cube & create strings to expand on title and rows - nCount = 1; - nDimensionIndex = 0; - sTitle = '%pQuote%Cube%pQuote%'; - sRow = '%pQuote%%pCube%%pQuote%'; - While( TabDim( pCube, nCount ) @<> '' ); - sDimension = TabDim( pCube, nCount ); - - ## Determine title string for the source cube - sTitle = sTitle|'%pFieldDelim%%pQuote%'|sDimension|'%pQuote%'; - # Determine row string for the source cube - sRow = sRow|'%pFieldDelim%%pQuote%%V'| numbertostring(nCount) |'%%pQuote%'; - - nCount = nCount + 1; - End; - nDimensionCount = nCount - 1; - - # Finish off the strings - sTitle = sTitle|'%pFieldDelim%%pQuote%Value%pQuote%'; - sRow = sRow|'%pFieldDelim%%pQuote%%sValue%%pQuote%'; - - # Create Processing View for source version - nRet = ExecuteProcess('}bedrock.cube.view.create', - 'pLogOutput', pLogOutput, - 'pStrictErrorHandling', pStrictErrorHandling, - 'pCube', pCube, - 'pView', cView, - 'pFilter', pFilter, - 'pSuppressZero', pSuppressZero, - 'pSuppressConsol', pSuppressConsol, - 'pSuppressRules', pSuppressRules, - 'pSuppressConsolStrings', pSuppressConsolStrings, - 'pDimDelim', pDimDelim, - 'pEleStartDelim', pEleStartDelim, - 'pEleDelim', pEleDelim, - 'pTemp', pTemp, - 'pSubN', pSubN - ); - - IF( nRet <> ProcessExitNormal() ); - sMessage = 'Error creating the view from the filter.'; - nErrors = nErrors + 1; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - If( pStrictErrorHandling = 1 ); - ProcessQuit; - Else; - ProcessBreak; - EndIf; - ENDIF; - - sParsedFilter = sBedrockViewCreateParsedFilter; - sFilterRow = '%pQuote%%pCube%%pQuote%%pFieldDelim%%pQuote%Filter%pQuote%%pFieldDelim%%pQuote%%sParsedFilter%%pQuote%%pFieldDelim%%pQuote%%pDimDelim%%pQuote%%pFieldDelim%%pQuote%%pEleStartDelim%%pQuote%%pFieldDelim%%pQuote%%pEleDelim%%pQuote%'; - - # Assign Datasource - DataSourceType = 'VIEW'; - DatasourceNameForServer = pCube; - DatasourceNameForClient = pCube; - DatasourceCubeView = cView; - DatasourceAsciiDelimiter= pFieldDelim; - DatasourceAsciiQuoteCharacter = ''; - nParallelRun = 0; -EndIf; - -### End Prolog ### -573,4 - -#****Begin: Generated Statements*** -#****End: Generated Statements**** - -574,50 - -#****Begin: Generated Statements*** -#****End: Generated Statements**** - -################################################################################################# -##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## -################################################################################################# - -# Set the output character set -SetOutputCharacterSet( cExportFile, pCharacterSet ); - -### Data Count ### -nDataCount = nDataCount + 1; - -# Output the title string -IF( nDataCount = 1 & pTitleRecord >= 1 ); - TextOutput( cExportFile, Expand(sTitle) ); -Endif; - -### Export filter into the 1st record of the file, it will be used from import process to zero out the corresponding slice, if specified -IF( nDataCount = 1 & pTitleRecord = 2 ); - TextOutput( cExportFile, Expand(sFilterRow) ); -Endif; - -### Export data from source version to file ### -If( value_is_string = 0 ); - sValue = NumberToString( nValue ); -EndIf; - -# Selects the correct TextOutput formula depending upon the number of dimensions in the cube -IF(SCAN( CHAR( 10 ), sValue ) > 0 ); - sValueCleaned = ''; - nNoChar = 1; - nLimit = LONG( sValue ); - WHILE( nNoChar <= nLimit ) ; - sChar = SUBST( sValue, nNoChar, 1 ); - IF( CODE( sChar, 1 ) <> 10 ); - sValueCleaned = sValueCleaned | sChar ; - ELSE; - sValueCleaned = sValueCleaned | ' '; - ENDIF; - nNoChar = nNoChar + 1; - END; - sValue = sValueCleaned; -ENDIF; - -# Output data -TextOutput( cExportFile, Expand(sRow) ); - -### End Data ### -575,41 - -#****Begin: Generated Statements*** -#****End: Generated Statements**** - -################################################################################################# -##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## -################################################################################################# - -### Delete source data ### -If( pZeroSource = 1 & nErrors = 0 & nParallelRun = 0 ); - If ( pCubeLogging <= 1 ); - sCubeLogging = CellGetS('}CubeProperties', pCube, 'LOGGING' ); - CubeSetLogChanges( pCube, pCubeLogging); - EndIf; - ViewZeroOut( pCube, cView ); - If ( pCubeLogging <= 1 ); - CubeSetLogChanges( pCube, IF(sCubeLogging@='YES',1,0) ); - EndIf; -EndIf; - -### Return code & final error message handling -If( nErrors > 0 ); - sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.'; - nProcessReturnCode = 0; - LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); - sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' ); - If( pStrictErrorHandling = 1 ); - ProcessQuit; - EndIf; -Else; - sDataCount = NUMBERTOSTRING (nDataCount); - sProcessAction = Expand( 'Process:%cThisProcName% exported %sDataCount% records from %pCube% based on filter %pFilter%.' ); - sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' ); - nProcessReturnCode = 1; - If( pLogoutput = 1 ); - LogOutput('INFO', Expand( sProcessAction ) ); - EndIf; - -EndIf ; - -### End Epilog ### -576,CubeAction=1511 DataAction=1503 CubeLogChanges=0 -930,0 -638,1 -804,0 -1217,1 -900, -901, -902, -938,0 -937, -936, -935, -934, -932,0 -933,0 -903, -906, -929, -907, -908, -904,0 -905,0 -909,0 -911, -912, -913, -914, -915, -916, -917,0 -918,1 -919,0 -920,50000 -921,"" -922,"" -923,0 -924,"" -925,"" -926,"" -927,"" +601,100 +602,"}bedrock.cube.data.export" +562,"VIEW" +586,"}APQ Staging TempSource" +585,"}APQ Staging TempSource" +564, +565,"qO5Xa]f2aD@Co0fuAafaFlDL3<1>PbdBASiCL4KVDH6\1pS5MlDAfrQSpmrjJE7?G4JM\zRPpGNwz_t9u1RPj6\dPULBYXXOG01?Ury;`MS>XFj]LU@n4HOrTrWQ79\ThQkh" +559,1 +928,0 +593, +594, +595, +597, +598, +596, +800, +801, +566,0 +567,"," +588,"." +589,"," +568,"""" +570,}TI_Dummy_View +571, +569,0 +592,0 +599,1000 +560,25 +pLogoutput +pStrictErrorHandling +pCube +pView +pFilter +pFilterParallel +pParallelThreads +pDimDelim +pEleStartDelim +pEleDelim +pSuppressZero +pSuppressConsol +pSuppressRules +pSuppressConsolStrings +pZeroSource +pCubeLogging +pTemp +pFilePath +pFileName +pDelim +pQuote +pTitleRecord +pSandbox +pSubN +pCharacterSet +561,25 +1 +1 +2 +2 +2 +2 +1 +2 +2 +2 +1 +1 +1 +1 +1 +1 +1 +2 +2 +2 +2 +1 +2 +1 +2 +590,25 +pLogoutput,0 +pStrictErrorHandling,0 +pCube,"" +pView,"" +pFilter,"" +pFilterParallel,"" +pParallelThreads,0 +pDimDelim,"&" +pEleStartDelim,"¦" +pEleDelim,"+" +pSuppressZero,1 +pSuppressConsol,1 +pSuppressRules,1 +pSuppressConsolStrings,0 +pZeroSource,0 +pCubeLogging,0 +pTemp,1 +pFilePath,"" +pFileName,"" +pDelim,"," +pQuote,"""" +pTitleRecord,1 +pSandbox,"" +pSubN,0 +pCharacterSet,"" +637,25 +pLogoutput,"OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)" +pStrictErrorHandling,"OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)" +pCube,"REQUIRED: Cube name" +pView,"OPTIONAL: Temporary view name" +pFilter,"OPTIONAL: Filter: Year¦ 2006 + 2007 & Scenario¦ Actual + Budget & Organization¦ North America Operations (Blank=whole cube)" +pFilterParallel,"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" +pParallelThreads,"OPTIONAL: Maximum number of threads to run when parallel processing is enabled ( if <2 will execute one thread, but parallel filter is still applied )" +pDimDelim,"OPTIONAL: Delimiter between dimensions (default value if blank = '&')" +pEleStartDelim,"OPTIONAL: Delimiter for start of element list (default value if blank = '¦')" +pEleDelim,"OPTIONAL: Delimiter between elements (default value if blank = '+')" +pSuppressZero,"OPTIONAL: Suppress Zero Values (1=Suppress)" +pSuppressConsol,"OPTIONAL: Suppress Consolidated Values? (1=Suppress)" +pSuppressRules,"OPTIONAL: Suppress Rule Values? (1=Suppress)" +pSuppressConsolStrings,"OPTIONAL: Suppress Strings on Consolidations (Skip = 1) (Default = 0)" +pZeroSource,"OPTIONAL: Zero Out view AFTER Copy? (Boolean 1=True)" +pCubeLogging,"Required: Cube Logging (0 = No transaction logging, 1 = Logging of transactions, 2 = Ignore Cube Logging - No Action Taken)" +pTemp,"OPTIONAL: Retain temporary view and Subset ( 0 = retain View and Subsets 1 = use temp objects)" +pFilePath,"OPTIONAL: Export Directory (will default to error file path)" +pFileName,"OPTIONAL: Export Filename (If Left Blank Defaults to cube_export.csv)" +pDelim,"OPTIONAL: AsciiOutput delimiter character (Default=comma, exactly 3 digits = ASCII code)" +pQuote,"OPTIONAL: AsciiOutput quote character (Accepts empty quote, exactly 3 digits = ASCII code)" +pTitleRecord,"OPTIONAL: Include Title Record in Export File? (Boolean 0=false, 1=true, 2=title and filter line Default=1)" +pSandbox,"OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)" +pSubN,"OPTIONAL: Create N level subset for all dims not mentioned in pFilter" +pCharacterSet,"OPTIONAL: The output character set (defaults to TM1CS_UTF8 if blank)" +577,101 +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 +V28 +V29 +V30 +V31 +V32 +V33 +V34 +V35 +V36 +V37 +V38 +V39 +V40 +V41 +V42 +V43 +V44 +V45 +V46 +V47 +V48 +V49 +V50 +V51 +V52 +V53 +V54 +V55 +V56 +V57 +V58 +V59 +V60 +V61 +V62 +V63 +V64 +V65 +V66 +V67 +V68 +V69 +V70 +V71 +V72 +V73 +V74 +V75 +V76 +V77 +V78 +V79 +V80 +V81 +V82 +V83 +V84 +V85 +V86 +V87 +V88 +V89 +V90 +V91 +V92 +V93 +V94 +V95 +V96 +V97 +V98 +V99 +V100 +Value +578,101 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +2 +579,101 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +580,101 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +581,101 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +582,101 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +VarType=32 ColType=827 +603,0 +572,395 +#Region CallThisProcess +# 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. +If( 1 = 0 ); + ExecuteProcess( '}bedrock.cube.data.export', 'pLogoutput', pLogoutput, + 'pStrictErrorHandling', pStrictErrorHandling, + 'pCube', '', 'pView', '', 'pFilter', '', + 'pFilterParallel', '', 'pParallelThreads', 0, + 'pDimDelim', '&', 'pEleStartDelim', '¦', 'pEleDelim', '+', + 'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', 1, + 'pZeroSource', 0, 'pCubeLogging', 0, 'pTemp', 1, + 'pFilePath', '', 'pFileName', '', + 'pDelim', ',', 'pQuote', '"', 'pTitleRecord', 1, 'pSandbox', pSandbox, 'pSubN', pSubN + ); +EndIf; +#EndRegion CallThisProcess + +#****Begin: Generated Statements*** +#****End: Generated Statements**** + +################################################################################################# +##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## +################################################################################################# + +#Region @DOC +# Description: +# This TI is designed to export data in a given cube to a flat file for a given "slice" (any dimension/element combination). +# +# Use case: Intended for development/prototyping or in Production environment. +# 1. Export data for import into another TM1 model to eliminate possibility of locking. +# 2. Export data for import into ERP system. +# +# Note: +# * Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort. +# * All other parameters are optional, however, the filter (pFilter) should be specified to limit the size of the file. +# * The default output path is the same as the error file path. +# * As this TI has a view as a data source it requires the implicit variables NValue, SValue and Value_is_String +# * To edit this TI in Architect a tmp cube with minimum 24 dims is needed as the preview data source or set the data +# source to ASCII and manually edit the TI in notepad after saving to add back the required implicit view variables +# * If using the pFilterParallel parameter the **single dimension** used as the "parallelization slicer" cannot appear in +# the pFilter parameter +# * When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time +# and passed to a recursive call of the process being added to pFilter. Each element name will also be appended to the filename +# +# Warning: +# As the *RunProcess* function currently has no mechanism to check for the state of the called process if more processes are +# released than available CPU cores on the server then this could lead to TM1 consuming all available server resources and a +# associated performance issue. Be careful that the number of slicer elements listed in pFilterParallel should not exceed the +# number of available cores. +#EndRegion @DOC + +##Global Variables +StringGlobalVariable('sProcessReturnCode'); +NumericGlobalVariable('nProcessReturnCode'); +StringGlobalVariable('sBedrockViewCreateParsedFilter'); + +### Constants ### +cThisProcName = GetProcessName(); +cUserName = TM1User(); +cTimeStamp = TimSt( Now, '\Y\m\d\h\i\s' ); +cRandomInt = NumberToString( INT( RAND( ) * 1000 )); +cMsgErrorLevel = 'ERROR'; +cMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%'; +cLogInfo = '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%.'; +cDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' ); +cLenASCIICode = 3; + +pFieldDelim = TRIM(pDelim); +pDimDelim = TRIM(pDimDelim); +pEleStartDelim = TRIM(pEleStartDelim); +pEleDelim = TRIM(pEleDelim); +nDataCount = 0; +nErrors = 0; + +## Default filter delimiters +If( pDimDelim @= '' ); + pDimDelim = '&'; +EndIf; +If( pEleStartDelim@= '' ); + pEleStartDelim= '¦'; +EndIf; +If( pEleDelim @= '' ); + pEleDelim = '+'; +EndIf; +sDelimDim = pDimDelim; +sElementStartDelim = pEleStartDelim; +sDelimelem = pEleDelim; + +## LogOutput parameters +IF( pLogoutput = 1 ); + LogOutput('INFO', Expand( cLogInfo ) ); +ENDIF; + +### Validate Parameters ### + +# If no cube has been specified then terminate process +If( Trim( pCube ) @= '' ); + sMessage = 'No cube specified.'; + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); +ElseIf( CubeExists( pCube ) = 0 ); + sMessage = Expand( 'Cube: %pCube% does not exist.' ); + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); +EndIf; + +## Validate the View parameter +If( TRIM(pView) @= '' ); + cView = cDefaultView ; +Else ; + cView = pView ; +EndIf; +cSubset = cView; + +## check operating system +If( Scan('/', GetProcessErrorFileDirectory)>0); +# sOS = 'Linux'; + sOSDelim = '/'; +Else; +# sOS = 'Windows'; + sOSDelim = '\'; +EndIf; + +# Validate file path +If(Trim( pFilePath ) @= '' ); + pFilePath = GetProcessErrorFileDirectory; +Else; + If( SubSt( pFilePath, Long( pFilePath ), 1 ) @= sOSDelim ); + pFilePath = SubSt( pFilePath, 1, Long( pFilePath ) -1 ); + EndIf; + If( FileExists( pFilePath ) = 0 ); + sMessage = Expand('Invalid export directory: %pFilePath%'); + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + EndIf; + pFilePath = pFilePath | sOSDelim; +EndIf; + +# Validate file name +If( pFileName @= '' ); + sBaseFileName = Expand('%pCube%_Export'); + sExt = '.csv'; + pFileName = sBaseFileName | '.csv'; +Else; + # determine file extension. If no file extension entered then use .csv as default + If( Scan( '.', pFileName ) = 0 ); + sExt = '.csv'; + sBaseFileName = pFileName; + Else; + sExt = SubSt( pFileName, Scan( '.', pFileName ), Long( pFileName ) ); + sBaseFileName = SubSt( pFileName, 1, Scan( '.', pFileName ) - 1 ); + EndIf; + pFileName = sBaseFileName | sExt; +EndIf; +cExportFile = pFilePath | pFileName; + +# Validate parallelization filter +If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); + sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); + If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 ); + sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.'; + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + EndIf; +EndIf; + +# Validate Max Threads +If( pParallelThreads > 0 ); + nMaxThreads = pParallelThreads; +Else; + nMaxThreads = 1; +EndIf; + +# Validate file delimiter & quote character +If( pFieldDelim @= '' ); + pFieldDelim = ','; +Else; + # If length of pFieldDelim is exactly 3 chars and each of them is decimal digit, then the pFieldDelim is entered as ASCII code + nValid = 0; + If ( LONG(pFieldDelim) = cLenASCIICode ); + nChar = 1; + While ( nChar <= cLenASCIICode ); + If( CODE( pFieldDelim, nChar ) >= CODE( '0', 1 ) & CODE( pFieldDelim, nChar ) <= CODE( '9', 1 ) ); + nValid = 1; + Else; + nValid = 0; + EndIf; + nChar = nChar + 1; + End; + EndIf; + If ( nValid<>0 ); + pFieldDelim=CHAR(StringToNumber( pFieldDelim )); + Else; + pFieldDelim = SubSt( Trim( pFieldDelim ), 1, 1 ); + EndIf; +EndIf; +If( pQuote @= '' ); + ## Use no quote character +Else; + # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code + nValid = 0; + If ( LONG(pQuote) = cLenASCIICode ); + nChar = 1; + While ( nChar <= cLenASCIICode ); + If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) ); + nValid = 1; + Else; + nValid = 0; + EndIf; + nChar = nChar + 1; + End; + EndIf; + If ( nValid<>0 ); + pQuote=CHAR(StringToNumber( pQuote )); + Else; + pQuote = SubSt( Trim( pQuote ), 1, 1 ); + EndIf; +EndIf; + +# Validate Sandbox +If( TRIM( pSandbox ) @<> '' ); + If( ServerSandboxExists( pSandbox ) = 0 ); + SetUseActiveSandboxProperty( 0 ); + nErrors = nErrors + 1; + sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.'); + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + Else; + ServerActiveSandboxSet( pSandbox ); + SetUseActiveSandboxProperty( 1 ); + EndIf; +Else; + SetUseActiveSandboxProperty( 0 ); +EndIf; + +# Validate Character Set +If(Trim( pCharacterSet ) @= '' ); + pCharacterSet = 'TM1CS_UTF8'; +EndIf; + +# Jump to Epilog if any errors so far +IF ( nErrors > 0 ); + DataSourceType = 'NULL'; + If( pStrictErrorHandling = 1 ); + ProcessQuit; + Else; + ProcessBreak; + EndIf; +ENDIF; + +# Branch depending on whether to do recursive calls to self on independent threads or run all in this thread +If( Scan( pEleStartDelim, pFilterParallel ) > 0 ); + sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 ); + sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) ); + If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim ); + sElementList = sElementList | pEleDelim; + EndIf; + ## Counting elements in element list + sElementListCount = sElementList; + nElements = 0; + While( Scan( pEleDelim, sElementListCount ) > 0 ); + nElements = nElements + 1; + sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) ); + End; + IF( Mod( nElements, nMaxThreads ) = 0 ); + nElemsPerThread = INT( nElements / nMaxThreads ); + ELSE; + nElemsPerThread = INT( nElements / nMaxThreads ) + 1; + ENDIF; + nThreadElCounter = 0; + While( Scan( pEleDelim, sElementList ) > 0 ); + sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 ); + sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) ); + # Do recursive process call with new RunProcess function + nThreadElCounter = nThreadElCounter + 1; + sDimDelim = If(pFilter @= '', '', pDimDelim ); + IF( nThreadElCounter = 1 ); + sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%'); + sFileName = Expand('%sBaseFileName%_%sDimParallel%_%sSlicerEle%'); + ELSE; + sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%'); + sFileName = Expand('%sFileName%+%sSlicerEle%'); + ENDIF; + IF( nThreadElCounter >= nElemsPerThread ); + sFileName = Expand('%sFileName%%sExt%'); + RunProcess( cThisProcName, 'pLogoutput', pLogoutput, + 'pCube', pCube, 'pView', '', + 'pFilter', sFilter, 'pFilterParallel', '', + 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, + 'pSuppressZero', pSuppressZero, 'pSuppressConsol', pSuppressConsol, 'pSuppressRules', pSuppressRules, + 'pZeroSource', pZeroSource, 'pCubeLogging', pCubeLogging, + 'pTemp', pTemp, 'pFilePath', pFilePath, 'pFileName', sFileName, + 'pDelim', pFieldDelim, 'pQuote', pQuote, 'pTitleRecord', pTitleRecord, 'pSandbox', pSandbox, 'pSuppressConsolStrings', pSuppressConsolStrings + ); + nThreadElCounter = 0; + sFilter = ''; + sFileName = ''; + ENDIF; + End; + ## Process last elements - only when filter is not empty (there are still elements) + IF( sFilter @<> '' ); + sFileName = Expand('%sFileName%%sExt%'); + RunProcess( cThisProcName, 'pLogoutput', pLogoutput, + 'pCube', pCube, 'pView', '', + 'pFilter', sFilter, 'pFilterParallel', '', + 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, + 'pSuppressZero', pSuppressZero, 'pSuppressConsol', pSuppressConsol, 'pSuppressRules', pSuppressRules, + 'pZeroSource', pZeroSource, 'pCubeLogging', pCubeLogging, + 'pTemp', pTemp, 'pFilePath', pFilePath, 'pFileName', sFileName, + 'pDelim', pFieldDelim, 'pQuote', pQuote, 'pTitleRecord', pTitleRecord, 'pSandbox', pSandbox, 'pSuppressConsolStrings', pSuppressConsolStrings + ); + ENDIF; + DataSourceType = 'NULL'; + nParallelRun = 1; +Else; + # No parallelization is being used. Proceed as normal and do everything internally + + # Determine number of dims in source cube & create strings to expand on title and rows + nCount = 1; + nDimensionIndex = 0; + sTitle = '%pQuote%Cube%pQuote%'; + sRow = '%pQuote%%pCube%%pQuote%'; + While( TabDim( pCube, nCount ) @<> '' ); + sDimension = TabDim( pCube, nCount ); + + ## Determine title string for the source cube + sTitle = sTitle|'%pFieldDelim%%pQuote%'|sDimension|'%pQuote%'; + # Determine row string for the source cube + sRow = sRow|'%pFieldDelim%%pQuote%%V'| numbertostring(nCount) |'%%pQuote%'; + + nCount = nCount + 1; + End; + nDimensionCount = nCount - 1; + + # Finish off the strings + sTitle = sTitle|'%pFieldDelim%%pQuote%Value%pQuote%'; + sRow = sRow|'%pFieldDelim%%pQuote%%sValue%%pQuote%'; + + # Create Processing View for source version + nRet = ExecuteProcess('}bedrock.cube.view.create', + 'pLogOutput', pLogOutput, + 'pStrictErrorHandling', pStrictErrorHandling, + 'pCube', pCube, + 'pView', cView, + 'pFilter', pFilter, + 'pSuppressZero', pSuppressZero, + 'pSuppressConsol', pSuppressConsol, + 'pSuppressRules', pSuppressRules, + 'pSuppressConsolStrings', pSuppressConsolStrings, + 'pDimDelim', pDimDelim, + 'pEleStartDelim', pEleStartDelim, + 'pEleDelim', pEleDelim, + 'pTemp', pTemp, + 'pSubN', pSubN + ); + + # Validate Sandbox + If( TRIM( pSandbox ) @<> '' ); + If( ServerSandboxExists( pSandbox ) = 0 ); + SetUseActiveSandboxProperty( 0 ); + nErrors = nErrors + 1; + sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.'); + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + Else; + ServerActiveSandboxSet( pSandbox ); + SetUseActiveSandboxProperty( 1 ); + EndIf; + Else; + SetUseActiveSandboxProperty( 0 ); + EndIf; + + + IF( nRet <> ProcessExitNormal() ); + sMessage = 'Error creating the view from the filter.'; + nErrors = nErrors + 1; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + If( pStrictErrorHandling = 1 ); + ProcessQuit; + Else; + ProcessBreak; + EndIf; + ENDIF; + + sParsedFilter = sBedrockViewCreateParsedFilter; + sFilterRow = '%pQuote%%pCube%%pQuote%%pFieldDelim%%pQuote%Filter%pQuote%%pFieldDelim%%pQuote%%sParsedFilter%%pQuote%%pFieldDelim%%pQuote%%pDimDelim%%pQuote%%pFieldDelim%%pQuote%%pEleStartDelim%%pQuote%%pFieldDelim%%pQuote%%pEleDelim%%pQuote%'; + + # Assign Datasource + DataSourceType = 'VIEW'; + DatasourceNameForServer = pCube; + DatasourceNameForClient = pCube; + DatasourceCubeView = cView; + DatasourceAsciiDelimiter= pFieldDelim; + DatasourceAsciiQuoteCharacter = ''; + nParallelRun = 0; +EndIf; + +### End Prolog ### +573,4 + +#****Begin: Generated Statements*** +#****End: Generated Statements**** + +574,50 + +#****Begin: Generated Statements*** +#****End: Generated Statements**** + +################################################################################################# +##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## +################################################################################################# + +# Set the output character set +SetOutputCharacterSet( cExportFile, pCharacterSet ); + +### Data Count ### +nDataCount = nDataCount + 1; + +# Output the title string +IF( nDataCount = 1 & pTitleRecord >= 1 ); + TextOutput( cExportFile, Expand(sTitle) ); +Endif; + +### Export filter into the 1st record of the file, it will be used from import process to zero out the corresponding slice, if specified +IF( nDataCount = 1 & pTitleRecord = 2 ); + TextOutput( cExportFile, Expand(sFilterRow) ); +Endif; + +### Export data from source version to file ### +If( value_is_string = 0 ); + sValue = NumberToString( nValue ); +EndIf; + +# Selects the correct TextOutput formula depending upon the number of dimensions in the cube +IF(SCAN( CHAR( 10 ), sValue ) > 0 ); + sValueCleaned = ''; + nNoChar = 1; + nLimit = LONG( sValue ); + WHILE( nNoChar <= nLimit ) ; + sChar = SUBST( sValue, nNoChar, 1 ); + IF( CODE( sChar, 1 ) <> 10 ); + sValueCleaned = sValueCleaned | sChar ; + ELSE; + sValueCleaned = sValueCleaned | ' '; + ENDIF; + nNoChar = nNoChar + 1; + END; + sValue = sValueCleaned; +ENDIF; + +# Output data +TextOutput( cExportFile, Expand(sRow) ); + +### End Data ### +575,41 + +#****Begin: Generated Statements*** +#****End: Generated Statements**** + +################################################################################################# +##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0~~## +################################################################################################# + +### Delete source data ### +If( pZeroSource = 1 & nErrors = 0 & nParallelRun = 0 ); + If ( pCubeLogging <= 1 ); + sCubeLogging = CellGetS('}CubeProperties', pCube, 'LOGGING' ); + CubeSetLogChanges( pCube, pCubeLogging); + EndIf; + ViewZeroOut( pCube, cView ); + If ( pCubeLogging <= 1 ); + CubeSetLogChanges( pCube, IF(sCubeLogging@='YES',1,0) ); + EndIf; +EndIf; + +### Return code & final error message handling +If( nErrors > 0 ); + sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.'; + nProcessReturnCode = 0; + LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) ); + sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' ); + If( pStrictErrorHandling = 1 ); + ProcessQuit; + EndIf; +Else; + sDataCount = NUMBERTOSTRING (nDataCount); + sProcessAction = Expand( 'Process:%cThisProcName% exported %sDataCount% records from %pCube% based on filter %pFilter%.' ); + sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' ); + nProcessReturnCode = 1; + If( pLogoutput = 1 ); + LogOutput('INFO', Expand( sProcessAction ) ); + EndIf; + +EndIf ; + +### End Epilog ### +576,CubeAction=1511 DataAction=1503 CubeLogChanges=0 +930,0 +638,1 +804,0 +1217,1 +900, +901, +902, +938,0 +937, +936, +935, +934, +932,0 +933,0 +903, +906, +929, +907, +908, +904,0 +905,0 +909,0 +911, +912, +913, +914, +915, +916, +917,0 +918,1 +919,0 +920,50000 +921,"" +922,"" +923,0 +924,"" +925,"" +926,"" +927,""