BookmarkSubscribeRSS Feed
BeerSultan
Calcite | Level 5

Brand new to SAS.

 

I'm doing something that I expect is relatively easy, but I'm struggling to get it right.  The requirement is basic - I'm reading in a long file with many rows, if a record matches a criteria I want it to be shipped to a different "bypass" file that I'll work on in a later process, but it should be removed from the original read-in file.

Environment is zOS - input file is defined and passed in via JCL (all working).
I get the following errors if I remove my actual logic - if I leave the FILENAME statement in without referencing it there's no errors.
ERROR: Invalid logical name.
ERROR: Error in the FILENAME statement.
ERROR: Invalid file, BYPASS_FILE.

 

FILENAME BYPASS_FILE BYPASS1;

/***********************************************************/
/* READ FILE */
/***********************************************************/
DATA DATAIN;
INFILE DATAIN;
INPUT
@ 00001 RECORD_NUMBER $CHAR8.
@ 01769 COMPONENT_STATUS $CHAR1.
;

/*******************************************************************/
/* CREATE BYPASS FILE - USED TO STORE RECORDS WHICH HAVE AN */
/* INACTIVE COMPONENT: COMPONENT_STATUS = I */
/*******************************************************************/
IF COMPONENT_STATUS = 'I' THEN DO;
 FILE BYPASS_FILE;
 PUT;
 DELETE;
END;

 

 

20 REPLIES 20
s_lassen
Meteorite | Level 14

I am not quite sure, but the message "Invalid logical name" sounds like it is the name "BYPASS_FILE" that is too long. It may be possible to have filename references in SAS (depending on the version) that are more than 8 characters, but if it gets passed to z/OS as a file reference/DD name, it probably won't work. Try using a shorter name, e.g. "BP_FILE".

BeerSultan
Calcite | Level 5
Yeah - no luck. Still giving invalid error.
BeerSultan
Calcite | Level 5

I was able to work through a couple iterations of it and got past those file-related errors.

The code thus far is as follows:

  IF component_status = 'I' THEN DO;
    FILE bypass;
    PUT
      @ 00001 record       $CHAR8.
    ;
    END;
    ELSE DO;
    FILE inputf
    PUT 
        @ 00001  lots of fields
        ;
  END;

For whatever reason the record meeting the IF criteria is still getting into the other file.  I want it just in the bypass file, and to be excluded from the data flowing in via the input file...I thought the IF condition would exclude it from going into the PUT for the other file.

Astounding
PROC Star
Please tell us this is just a typo and you really do have a semicolon after

FILE inputf
Kurt_Bremser
Super User

As soon as a FILE statement executes, it opens the file, and the file is kept open. Multiple FILE statements mean multiple concurrent destinations.

The FILE Statement documentation shows how the output file can be changed with the FILEVAR= option, but you have to use physical names in this variable, not file references.

Tom
Super User Tom
Super User

The indentation is a little messed up but it looks like you are just missing s semicolon.

data _null_;
  set have;
  IF component_status = 'I' THEN DO;
    FILE bypass;
    PUT
      @ 00001 record       $CHAR8.
    ;
  END;
  ELSE DO;
    FILE inputf;
    PUT 
        @ 00001  lots of fields
    ;
  END;
run;

So that code is WRITING from a DATASET to a FILE.  Which is not the impression I got from your original post.  It sounded more to me like you were trying to READ from a file and spit out the other LINES from the file to a separate file.

So a data step like this will create WANT dataset from the input file IN.  It will check something on the line and decide whether it should write that line to the OUT text file or continue with the rest of the data step that reads the line and does any other things like calculating any derived variables.

data want;
  infile IN ;
  file OUT ;
  input @1 check $ @1 @ ;
  if check='X' then do;
     put _infile_;
     delete;
  end;
  input ....;
  ....
run;

And if what you meant was just about SAS datasets then no need for FILE or INFILE or PUT or INPUT statements.

data good bad;
  set have;
  if check='X' then output bad;
  else output good;
run;
Kurt_Bremser
Super User

The parameter of a FILE statement must either be a file reference (without quotes) created with a FILENAME statement or coming from the JCL, or a physical path name enclosed in quotes.

Since you did not use quotes, the file reference must be 8 or less characters long, and must have been defined upstream (in the JCL or SAS code).

If you want to supply a physical name, it must meet the requirements of z/OS.

BeerSultan
Calcite | Level 5
I do have it coming via JCL and it's named accordingly. I ended up abandoning using the FILENAME approach altogether...I don't know how to make it work that way.

BYPASS DD DSN=XY.#xyz1234.TEST.DATA.BYPASS,
DISP=(NEW,CATLG,DELETE),UNIT=TST1,
DATACLAS=FXB080CP,LRECL=40,
SPACE=(40,(1,1),RLSE),AVGREC=K
Tom
Super User Tom
Super User

@BeerSultan wrote:
I do have it coming via JCL and it's named accordingly. I ended up abandoning using the FILENAME approach altogether...I don't know how to make it work that way.

BYPASS DD DSN=XY.#xyz1234.TEST.DATA.BYPASS,
DISP=(NEW,CATLG,DELETE),UNIT=TST1,
DATACLAS=FXB080CP,LRECL=40,
SPACE=(40,(1,1),RLSE),AVGREC=K

When you define the access with a DD statement then in the FILE statement you just use the DDNAME you used in the DD statement.  Which in your example DD statement is BYPASS.

file bypass ;

If you wanted to mimic the DD statement in a SAS filename statement instead then it would look very similar to the DD statement, but it would look like SAS code instead of JCL code. 

 

Check the syntax of the filename statement on z/OS.

filename bypass disk 'XY.#xyz1234.TEST.DATA.BYPASS' DISP=(NEW,CATLG,DELETE) ..... ;

 

BeerSultan
Calcite | Level 5

I've got it mostly working, but now the record is in both files...  I want the record to go to only the bypass file when it's found, otherwise only go to the other file (which is just the incoming file)

  IF COMPONENT_STATUS = 'I' THEN DO;
    FILE LTABYPSS;
    PUT
      @ 00001 RECORD_NUMBER       $CHAR8.
    ;
    END;
    ELSE DO;
    FILE DATAIN
    PUT
        @ 00001  lots of values
...
        ;
  END;

 

 

Kurt_Bremser
Super User

As already said, you need a single FILE statement with a FILEVAR option, and change the contents of that variable. Or you run two separate DATA steps, one for each output file.

BeerSultan
Calcite | Level 5

It's part of an existing process that I'm expanding to exclude this bypass file - which is why I was attempting to use the existing reading infile processing and just shunt off the "found" records that I want to exclude.  The bypass file will be used in a next step to build a report with counts/rationale.

 

I don't want to mess with the existing processing too much because it'll cause a larger change than what I'm comfortable doing.

Tom
Super User Tom
Super User

@BeerSultan wrote:

It's part of an existing process that I'm expanding to exclude this bypass file - which is why I was attempting to use the existing reading infile processing and just shunt off the "found" records that I want to exclude.  The bypass file will be used in a next step to build a report with counts/rationale.

 

I don't want to mess with the existing processing too much because it'll cause a larger change than what I'm comfortable doing.


You have not provided enough information to give you complete solution, only suggestions.

 

So if you have an existing program that reads lines from a text file (either to make a dataset or make another file, I cannot tell which from your descriptions and the snippets of programs you have shared) that you now have to change it to also have it copy some of the lines from the source text files to a new text file.

 

So you need to change it in the following ways.  

1) Come up with logic that detects which lines it is that you want to write to the file.

2) Conditionally execute the FILE and PUT statement to write the line to the new file.

 

I showed this before, so let's try again.  Let's assume you have some normal program that read a text file into dataset.

data want;
  infile myfile ;
  input ..... ;
run;

So first you have to add the logic to detect the lines you want to skip.  This could be a simple as jut reading some part of the line that indicates what type of line it is.  So perhaps you want reject the lines that have X in column 32.

Then you can add code that will write those lines to the new file and not include them in the normal output of the data step.

data want;
  infile myfile ;
  input @32 check $1. @1 @ ;
  if check='X' then do;
    file newfile;
    put _infile_;
    delete;
  end;
  input ..... ;
  drop check;
run;

 

 

 

 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 20 replies
  • 551 views
  • 6 likes
  • 5 in conversation