Want to know The Truth About CPM?
Showing posts with label DOS. Show all posts
Showing posts with label DOS. Show all posts

01 April 2011

Stupid Programming Tricks #8

Introduction to the introduction

I wrote this (or as you’ll see in a minute, I didn’t  write this) quite a while ago and was holding off on releasing it because…well because I had other things to post.

Now I see that Robb Salzmann has posted something pretty similar to what I-didn’t-but-someone-else wrote.

Think of this as an alternate take on his post, or his post is an alternate of this post.  You decide.

Introduction

Are you an Antimimetic or a Mimetic?  In other words, does art imitate life, or life imitate art?  

I’m pretty sure my name isn’t Tom Sawyer, and yet I manage to get others to whitewash Aunt Polly’s fence.

This time it’s Frank Chow who’s done all of the hard work.

The problem

Set substitution variables for the current Actual month and year.  Big deal, right?  Any automated system worth its salt does this.  

But where do those dates come from?  Manual assignment?  Magic?

Frank went for code (Is there really any other way?) and had an additional requirement – that the current month increments on the 25th of the month.  And oh yes, and it had to handle the extra-special case of January.

NB – The fiscal year is the same as the calendar year.  It has to be for the solution below to work as you’ll shortly see.

The solution

DOS will never die, will it?  It is breathtakingly cryptic and quite powerful in its limited way.  What’s not to love?  

Let’s dive in:

Setup the Day, Month, and Year variables

:: ********************* Set up the Day, Month, Year Variables **************************
   FOR /f "tokens=1-4 delims=/ " %%a in ('date /t') do (
    set day=%%a
    set mm=%%b
    set dd=%%c
    set yy=%%d
    )
                                                                             
 set /a pr_mm=%mm%-1
 set /a pr_yy=%yy%-1
Pretty cool stuff here – the code is stripping the output of date /t using the backslash as a delimiter and then putting the day, month number, day number, and two digit year into four temporary variables.

Setting up the strings

:: ***************** set up mapping table ************************
  set monthmap=00-Dec;01-Jan;02-Feb;03-Mar;04-Apr;05-May;06-Jun;07-Jul;08-Aug;09-Sep;10-Oct;11-Nov;12-Dec
::*************** set current month variable ************
 CALL SET cur_month=%%monthmap:*%mm%-=%%
 SET cur_month=%cur_month:;=&rem.%

::*************** set prior month variable **************
 CALL SET pr_month=%%monthmap:*%pr_mm%-=%%
 SET pr_month=%pr_month:;=&rem.%

echo current_month: %cur_month%
echo prior_month: %pr_month%

::*************** set current & prior year variables ***********
 set cur_yr=FY%yy:~-2%
 set pr_yr=FY%pr_yy:~-2%

echo current_year: %cur_yr%
echo prior_year: %pr_yr%
Here a key-value pair is used with CALL SET to translate the month numbers in the variable %mm% to three character strings and is also used to append “FY” to the two digit year values in %yy%.

Here’s a good guide to string manipulation.  You’ll find a section similar to the above in the example called “Map and Lookup - Use Key-Value pair list to lookup and translate values”.

Handle month end and January special case

::************ set up CurrActMonth & CurrActYear variables ***************                                                                                         
 IF %cur_month% EQU Jan goto Var_Jan
 IF %dd% LSS 25 goto before25
 IF %dd% GEQ 25 goto after25
 
:Var_Jan
 IF %dd% LSS 25 goto before25_Jan
 goto after25

:before25_Jan
 SET CurrActMonth=Dec
 SET CurrActYear=%pr_yr%
 goto End
  
:before25
 SET CurrActMonth=%pr_month%
 SET CurrActYear=%cur_yr%
 goto End
  
:after25
 SET CurrActMonth=%cur_month%
 SET CurrActYear=%cur_yr%
 goto End
:End

echo CurrActMonth: %CurrActMonth%
echo CurrActYear: %CurrActYear%

Ever wonder what the DOS commands are for >, >, <>, etc.?  Check them out here.

Run it if needed

:: ***************** Excute the MAXL script if the date is 25th ***********************
 IF %dd% EQU 25 goto MAXL_update_date
 exit

REM /============ excute MAXL script to update the Substitution Variables ======================/
:MAXL_update_date
 essmsh SubVar_CurrActMonth_Year.msh
This code gets run every night.  If it’s the 25th, run the MaxL code, otherwise exit.

Do it in MaxL

/* --------------------------------------------------------------------------
*  LOGIN AND SETUP SCRIPT VARIABLES - &CurrActMonth and &CurrActYear
* -------------------------------------------------------------------------- */

/* NB -- user, password, and server are set up separately as Windows
  environment variables.    */
login "$ESS_USERID" "$ESS_PASSWD" on "$ESS_SERVER";

/* ---------------- SET UP SUBSTITUTION VARIALBES --------------------------- */
alter system set variable 'CurrActMonth' $CurrActMonth;
alter system set variable 'CurrActYear' $CurrActYear;

logout;
exit;
Remember, the Windows CMD script code set the temporary OS environment variables CurrActMonth and CurrActYear.  These are referenced in MaxL with a “$” in front of the variable name.

Conclusion

This code does three things:
  1. Figures out the current month and year based on system date
  2. Uses some cool DOS functions
  3. Sets Essbase substitution variables if it’s the 25th of the month and oh by the way handles year end pretty well


Frank asked me what I thought about it – was it any good, could I make improvements, etc.  Some say the greatest form of flattery is imitation.  Is ripping code off and using it yourself an even greater form of flattery?  Whatever your definition, I plan on using this code when I have the same need.

You can get the whole code stream here.  Run it with the PAUSE statements in to understand what it’s doing – take those statements out when you want to use it.

07 August 2010

Stupid programming tricks #1

Introduction

This is going to be one of an occasional, short (can it be true), little techniques that I’ve picked up along the way.  This one isn’t even original, but it works so well I just have to write about it.

I had to do an inventory of calc scripts, rule files, and report scripts.

There were lots of them.  Lots.  More than you could ever imagine.  And, I needed to get a list of all of them quickly.

Oh, I could have used the Most awesome excellent Language ever, and entered:
display calculation all ;

But that would only have given me the calc scripts.  What about reports?  What about rules?

I could have used MaxL again with a different display command, display object, but the syntax for that command confuses my simple brain.

A better way

It occurred to me that those items were all available at the OS level as they are all files with .csc, .rul, and rep extensions.

How could I quickly, painlessly, consistently, etc., etc., get this information into a text file so I could hoover it into SQL or Excel to report on?

Why good old DOS, of course.  Yes, I am old enough to remember DOS 1.0, and DOS-compatible PCs (which were not the same as PC compatible), and CPM, and when dinosaurs walked the earth with me and my good buddy down at the quarry, Fredrick Joseph Flintstone.  And I like DOS, heaven help me.  Succinct, powerful-ish, and cryptic.  What’s a hacker not to like?

And guess, what, DOS has this nifty little recursion function called FOR.  If you care to read all about it, type FOR /? at the command prompt on your PC or check out this nice blog series that I wish I had found before I figured this out.

What’s it look like?

So simple it hurts:

for /r %d in (*.msh) do echo %d >> c:\temp\MaxLOutput.txt

Enter that from whatever directory you care to start in and FOR /R will do the rest for every single MaxL script that’s in the descendants of the launching directory.

And here’s the output (I launched it from c:\tempdir):
C:\Tempdir\ODTUG_2009\CatchThatError.msh
C:\Tempdir\ODTUG_2009\connect.msh
C:\Tempdir\ODTUG_2009\disconnect.msh
C:\Tempdir\ODTUG_2009\encryptionpost.msh
C:\Tempdir\ODTUG_2009\HelloMurphy.msh
C:\Tempdir\ODTUG_2009\local.msh
C:\Tempdir\ODTUG_2009\nested.msh
C:\Tempdir\ODTUG_2009\NoError.msh
C:\Tempdir\ODTUG_2009\parameters.msh
C:\Tempdir\ODTUG_2009\parameters_environment.msh
C:\Tempdir\ODTUG_2009\properties.msh
C:\Tempdir\ODTUG_2009\shell.msh
C:\Tempdir\ODTUG_2009\SpoolMe.msh
C:\Tempdir\ODTUG_2009\tobeencrypted.msh
C:\Tempdir\ODTUG_2009\tobeencrypted.mshs
C:\Tempdir\ODTUG_2009\9.2 metaread\Copy of
C:\Tempdir\ODTUG_2009\9.2 metaread\Metaread\deprecated\filename.msh
C:\Tempdir\ODTUG_2009\deprecated\Copy of sample3.msh
C:\Tempdir\ODTUG_2009\deprecated\sample3.msh
C:\Tempdir\ODTUG_2009\deprecated\sample3a.msh
C:\Tempdir\ODTUG_2009\deprecated\sample4.msh
C:\Tempdir\ODTUG_2009\deprecated\sample5.msh
C:\Tempdir\ODTUG_2009\deprecated\sample6.msh
C:\Tempdir\ODTUG_2009\deprecated\sample3.mshs
C:\Tempdir\ODTUG_2009\deprecated\sample3a.mshs
C:\Tempdir\ODTUG_2009\deprecated\sample4.mshs
C:\Tempdir\ODTUG_2009\ODTUG_2009\call_metaread_add_filters.msh
C:\Tempdir\ODTUG_2009\ODTUG_2009\call_metaread_add_filters.mshs
C:\Tempdir\ODTUG_2009\ODTUG_2009\Metaread_Add_Filters.msh
C:\Tempdir\ODTUG_2009\ODTUG_2009\Write_Filters_To_Disc.msh
C:\Tempdir\ODTUG_2009\ODTUG_2009\write_filters_to_disc.mshs

How about calcs?

for /r %d in (*.csc) do echo %d >> c:\temp\CalcOutput.txt

And here’s the output (I launched it from c:\tempdir):
C:\Tempdir\NOTTELLING\NOTTELLING\XPort.csc
C:\Tempdir\NOTTELLING\NOTTELLING\Bad order FinPlan4_GLTest\ActCmbnd.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\GL\GL.ActCmbnd.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\GL\GL.allocav2.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\GL\GL.AllocAvg2.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\GL\GL.FillQBR.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\GL\GL.QBRTEST2.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\GL\GL.X.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\PGM\AdvaLiqn.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\PGM\OPSCopy.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\PGM\PopActE.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\PGM\ProgRecp.csc
C:\Tempdir\NOTTELLING\NOTTELLING\NOTTELLING Backup\NOTTELLING Backup\PGM\RecvBal.csc
C:\Tempdir\NOTTELLING\NOTTELLING\FinPlan4\ActCalc.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\$calc.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\$test.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\71937158.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\AdminOH.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\AggCMth.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\BaseAct.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\BB2YTD.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\BR2.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\CComp.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\ClrAdj.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\Comp.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\Fringe.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\Pipeline.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\RevCycle.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\Revenue.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\Seed7699.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\SeedCalc.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\Taxes.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\Transfer.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\WSGrant.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\YTD2BB.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\Adj_calcs\YTDAct.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\TUSMFRBS_PandL\$calc.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\TUSMFRBS_PandL\$test.csc
C:\Tempdir\REDACTED\Phase I\Adjustment\TUSMFRBS_PandL\$test2.csc

Conculsion

And that’s it – this isn’t Oracle EPM based – it can be for any kind of file.

Not exactly hacking Essbase, but it’s a little out of the ordinary and a *huge* timesaver if you’re trying to get lists fast.