In this blog, I show how you can read in a delimited text file containing reference data using a custom step. Then, use that reference data in a dynamic drop-down within another custom step. These custom steps use the File or Folder Selector control (available in 2021.2.1) and the ability to create a Dynamic Drop-down List using the drop-down list control (available in 2021.2.3).
Custom Step to Read-In a Reference File
This custom step reads in a delimited reference file, so its values can be used in a SAS Studio Flow. The reference file can either be in SAS Content or on the SAS Server. The first row of the reference file must contain the column names.
Select any image to see a larger version. Mobile users: To view the images, select the "Full" version at the bottom of the page.
Below is the JSON code for the UI of the custom step:
{
"showPageContentOnly": true,
"pages": [
{
"id": "refFileImport",
"type": "page",
"label": "Import Delimited Reference File",
"children": [
{
"id": "text1",
"type": "text",
"text": "Read in a delimited Reference file from either SAS Content or SAS Server.",
"visible": ""
},
{
"id": "referenceFile",
"type": "path",
"label": "Select the reference file",
"pathtype": "file",
"placeholder": "",
"required": true,
"visible": ""
},
{
"id": "note",
"type": "text",
"text": "NOTE: This must be a delimited text file and the first row of the file must contain the column names.",
"visible": ""
},
{
"id": "delimiterType",
"type": "dropdown",
"label": "Select file delimiter",
"items": [
{
"value": "Comma"
},
{
"value": "Space"
},
{
"value": "Tab"
},
{
"value": "Other"
}
],
"required": false,
"placeholder": "",
"visible": ""
},
{
"id": "otherDelimiter",
"type": "textfield",
"label": "If Other, enter delimiter",
"placeholder": "",
"required": true,
"visible": [
"$delimiterType",
"=",
"Other"
]
},
{
"id": "numRows",
"type": "numberfield",
"label": "Enter number of rows to guess column data types",
"placeholder": "",
"required": true,
"max": 10000,
"min": 10,
"excludemin": false,
"excludemax": false,
"visible": ""
},
{
"id": "outTable",
"type": "outputtable",
"label": "Output Table",
"required": true,
"placeholder": "",
"visible": ""
}
]
}
],
"values": {
"referenceFile": "",
"delimiterType": {
"value": "Comma"
},
"otherDelimiter": "",
"numRows": 100,
"outTable": {
"library": "",
"table": ""
}
}
}
Below is the code performed by the custom step:
/**** Read in a delimited text file. The intention of this custom step is this file would contain reference data that is needed in the SAS Studio Flow. ****/
/**** NOTE: The first row of the file must contain a header row ****/
/* Macro for default SAS Server temp folder */
%let srvrFolder=/tmp;
/* Parse parts of the selected Reference File */
%let fileLoc=%qscan(&referenceFile,1,:);
%put FileLocation: &fileLoc;
%let filePathwithName="%qscan(&referenceFile,2,:)";
%put ReferenceFilePathWithName: &filePathwithName;
%let refFileName="%qscan(&referenceFile,-1,/)";
%put ReferenceFileName: &refFileName;
%let noquotePath=%qscan(&referenceFile,2,:);
%put PathWithNoQuote: &noquotePath;
%let parentFolderLength=%eval(%length(&noquotePath)-%length(&refFileName))+1;
%let refFilePath="%qsubstr(&noquotePath,1,&parentFolderLength)";
%put ReferenceFilePath: &refFilePath;
/*Perform this section if file on SAS Content */
%if &fileLoc=sascontent %then %do;
filename refFile filesrvc folderpath=&refFilePath filename=&refFileName;
filename srvrFile '&srvrFolder.\%dequote(&refFileName)';
data _null_;
infile refFile;
file srvrFile;
input @;
put _infile_;
run;
%end;
/*Perform this section if file on SAS Server */
%if &fileLoc=sasserver %then %do;
filename srvrFile &filePathwithName;
%end;
/* Import selected reference file */
%if &delimiterType=Comma %then %do;
proc import datafile=srvrFile
out=&outTable replace
dbms=dlm;
delimiter=',' ;
getnames=YES;
guessingrows=&numRows;
run;
%end;
%if &delimiterType=Tab %then %do;
proc import datafile=srvrFile
out=&outTable replace
dbms=tab;
getnames=YES;
guessingrows=&numRows;
run;
%end;
%if &delimiterType=Other %then %do;
proc import datafile=srvrFile
out=&outTable replace
dbms=dlm;
delimiter="&otherDelimiter" ;
getnames=YES;
guessingrows=&numRows;
run;
%end;
%if &delimiterType=Space %then %do;
proc import datafile=srvrFile
out=&outTable replace
dbms=dlm;
delimiter='20'x ;
getnames=YES;
guessingrows=&numRows;
run;
%end;
Note: I am a novice at SAS coding, so there may other (better) ways to accomplish this.
Custom Step with Dynamic Drop-Down List
The input data provided to this custom step is used to dynamically create the list of values for the drop-down. In my example, the input data is the discount reference data read in using the above discussed custom step.
Below is the JSON code for the UI of the custom step:
{
"showPageContentOnly": true,
"pages": [
{
"id": "discount",
"type": "page",
"label": "Select Discount Percentage",
"children": [
{
"id": "text1",
"type": "text",
"text": "Example of calculating the discount multipler. Input must contain percentage values.",
"visible": ""
},
{
"id": "inTable",
"type": "inputtable",
"label": "Input Discount Table",
"required": true,
"placeholder": "",
"visible": ""
},
{
"id": "discountColumn",
"type": "columnselector",
"label": "Select the discount tier column",
"order": false,
"columntype": "c",
"max": 1,
"min": 1,
"visible": "",
"table": "inTable"
},
{
"id": "discountPercentage",
"type": "dropdown",
"label": "Discount Percentage",
"items": {
"ref": "discountColumn"
},
"required": true,
"placeholder": "",
"visible": ""
},
{
"id": "outTable",
"type": "outputtable",
"label": "Output DiscountTable",
"required": false,
"placeholder": "",
"visible": ""
}
]
}
],
"values": {
"inTable": {
"library": "",
"table": ""
},
"discountColumn": [],
"discountPercentage": null,
"outTable": {
"library": "",
"table": ""
}
}
}
Below is the code performed by the custom step:
/* Convert Discount Percentage to Numeric Amount */
%let discPercentage = %qsubstr(&discountPercentage,1,%length(&discountPercentage)-1);
%put DiscountPercentage: &discPercentage;
%let discCalculation = %sysevalf((100-&discPercentage)/100);
%put DiscountCalculation: &discCalculation;
Note: I am a novice at SAS coding, so there may other (better) ways to accomplish this.
SAS Studio Flow Example using the Custom Steps
The GIF below shows the two custom steps in action in a SAS Studio Flow and the selected discount percentage is then used to calculate the car price based on its MSRP value.
Summary
For more information on custom steps, please refer to its documentation.
Thanks to my SAS colleagues Tina Tart for explaining current state of the custom step controls and Tan Phan for his code to parse the parts of the selected file. Also, thanks to @StephenFoerster for his coding assistance and support.
Find more articles from SAS Global Enablement and Learning here.
... View more