Help using Base SAS procedures

Changing input based on Global Variables

Reply
N/A
Posts: 0

Changing input based on Global Variables

Hello all!

In a mainframe environment, SAS 9.1.3 Service Pack 4

I am attempting to read in a file in a group of variables, the number of variables depends on the file record length and the number of columns I want in each variable.

Meaning, if the file length is 80, and I want blocks of data 10 columns long, I need it to create 8 different variables and read them in with positions in relation to the variable.
@01 VARBLK1
@11 VARBLK2 and so on

The four variables bolded will be assigned by the user, but can change at any time. In my code below, I need the INTN (being the variable name) so I can make sense of the information I receive

I was trying the following code with no success.

%LET NWLOC = %FILEDATA(CMPFILE1,6);
%LET BLK = 10 ;
%LET PRIMSTR = 001 ;
%LET PRIMFMT = 9. ;
%LET PRIMVAR = INTN ;


DATA FRSTFILE;
INFILE
CMPFILE1
MISSOVER END=LASTREC
;

FLELNGTH = INPUT(&NWLOC,5.);
BLKSIZE = INPUT(&BLK,5.);
VARNM = FLELNGTH/BLKSIZE;

CALL SYMPUT('VARNUM',VARNM);

SELECT ( &BTCH_FILE_TYPE );
WHEN ( 'BLOCK' )
INPUT
@ &PRIMSTR &PRIMVAR &PRIMFMT @;

ARRAY FLEBLK (&VARNUM);
DO I = 0 TO &VARNUM;
@((I*&BLK)+ 1) FLEBLK(I) $CHAR&BLK.@;
END;


END;

RUN;

Currently, I run into this.... Line generated by the macro variable "VARNUM".
80/10
ERROR 180-322: Statement is not valid or it is used out of proper order.

I assume it is because the VARNUM isn't actually performing the calculation as I had hoped. Alternate suggestions or approaches would be greatly appreciated.
Super User
Posts: 5,430

Re: Changing input based on Global Variables

Posted in reply to deleted_user
You are running into the problem (often discussed at the forums): macro variable created by CALL SYMPUT are not assigned until the end of the data step.

But looking at your code, it seems that you don't need ant input data to calculate VARNUM. So I suggest that you do this calculation in a preceding data _null_ step, or using %sysfunc together with %let.

Don't know if this will make your whole program to work, but I hope it will resolve your error issue.

Regards,
Linus
Data never sleeps
N/A
Posts: 0

Re: Changing input based on Global Variables

Posted in reply to deleted_user
teter09

you have a lot of redundant processing in your array coding where it is mixed up with macro variables.
The INPUT statement is very powerful.You can read these data into a range of variables with something like [pre] input @&PRIMSTR &PRIMVAR &PRIMFMT
@&primStr ( fleblk1 - fleblk&Nblocks)( $char&Wblocks..) [/pre]where &Nblocks is the expected number of blocks on the line and &Wblocks provides the width of each of these blocks. I think the values you need for these macro variables can be determined before you read the data blocks. Based on your posting, the information could be found with something like[pre]%LET NWLOC = %FILEDATA(CMPFILE1,6);
%LET BLK = 10 ;
%LET PRIMSTR = 001 ;
%LET PRIMFMT = 9. ;
%LET PRIMVAR = INTN ;

%let nBlocks = %eval( &nwloc / &BLK ) ;
%let wBlocks = &blk ;[/pre]

You may have some other use for the array, but no need to use it on the input statement to read into blocks.

If you need the block width to vary with the input record length, you could use the $VARYING informat and derive how wide each should be from the LENGTH= infile option.

Split up your problems.
Those which depend on what is in the data rows being read, should be solved in data step processing. Those which don't change throughout the data or the running of the data step, can be prepared beforehand usually with simple macro variable processing like above.

PeterC
Ask a Question
Discussion stats
  • 2 replies
  • 119 views
  • 0 likes
  • 2 in conversation