6.4 Creating & Applying Custom Formats with PROC FORMAT
Key Takeaways
PROC FORMAT creates custom value formats (VALUE), informats (INVALUE), and picture formats (PICTURE) to transform data display without altering underlying stored data values.
Character format names must begin with a dollar sign ($), cannot end in a period in the VALUE statement, and must not exceed 32 characters or end in a number.
The FMTLIB option displays a detailed catalog listing of all user-defined formats, their value ranges, and assigned labels in procedure output.
Custom formats can be exported to SAS datasets using CNTLOUT= and recreated from dataset control files using CNTLIN=, enabling portable format management.
In a FORMAT statement, a period (.) must be appended to the format name (e.g., format status $statfmt.;) to distinguish custom formats from dataset variables.
6.4 Creating & Applying Custom Formats with PROC FORMAT
In SAS programming, a fundamental architectural principle is the separation of stored data values from displayed formatted values. Raw data stored on disk (e.g., numeric codes 1, 2, 3 or raw dates 24103) should remain compact and un-mutated, while reports and summaries display human-readable text labels (e.g., 'North America', 'Europe', 'Asia' or '07AUG2026').
The PROC FORMAT procedure enables programmers to build custom user-defined formats, informats, and picture patterns. Formats facilitate continuous-to-categorical binning, data standardization, label mapping, and dynamic reporting without modifying the underlying dataset.
1. Fundamental Syntax & Format Types
PROC FORMAT supports three distinct user-defined structures:
VALUEStatement: Maps stored data values (or value ranges) into formatted text labels for output display.INVALUEStatement: Defines informats to convert raw input strings into formatted values during data ingestion (INPUTstatement orINPUT()function).PICTUREStatement: Defines custom templates for printing numeric data using digit masks (e.g., formatting 10-digit integers as phone numbers(###) ###-####or Social Security Numbers).
PROC FORMAT <LIBRARY=libref<.catalog>> <options>;
VALUE [$]format_name
range-1 = 'label-1'
range-2 = 'label-2'
other = 'default-label';
RUN;
2. Rules for Naming Custom Formats
Custom format names must comply with strict SAS naming rules. The Base exam frequently tests syntax errors arising from invalid format names:
| Rule | Character Formats | Numeric Formats |
|---|---|---|
| Prefix / Dollar Sign | MUST begin with a dollar sign ($). | CANNOT begin with a dollar sign ($). |
| Maximum Length | Up to 32 characters (including $). | Up to 32 characters. |
| Ending Semicolon/Period | Do NOT include a period in PROC FORMAT. | Do NOT include a period in PROC FORMAT. |
| Ending Character | Cannot end in a digit. | Cannot end in a digit. |
| Reserved Names | Cannot match built-in SAS format names (e.g., $CHAR, $HEX). | Cannot match built-in SAS format names (e.g., DATE7, DOLLAR12). |
Exam Tip: In
PROC FORMAT, the format name must NEVER end with a period (e.g.,value $genderfmt). However, when applying the format in aFORMATstatement orPUT()function, a period MUST be appended (e.g.,format Gender $genderfmt.;).
3. Range Syntax & Mapping Operators in VALUE Statements
When binning numeric values or mapping strings, PROC FORMAT offers rich range specifications:
| Range Syntax | Meaning / Example | Included Values |
|---|---|---|
| Single Values / Lists | 1, 2, 3 = 'Low' or 'M', 'F' = 'Valid' | Exact matching values |
| Continuous Range | 18 - 29 = 'Young Adult' | Inclusive bounds () |
Exclusive Bounds (<) | 18 -< 30 = '18 to 29'; 30 <- 50 = '31 to 50' | 18 -< 30 (); 30 <- 50 () |
| Open-Ended Keywords | LOW - 17 = 'Minor'; 65 - HIGH = 'Senior' | LOW includes all negative infinity up to 17. HIGH includes up to maximum value. |
OTHER Keyword | OTHER = 'Unknown / Invalid' | Catches all values not explicitly covered by preceding ranges (including missing values unless handled). |
/* Comprehensive PROC FORMAT example with numeric ranges and character maps */
proc format;
/* Character format mapping */
value $status_fmt
'A' = 'Active'
'I' = 'Inactive'
'P' = 'Pending'
other = 'Unassigned';
/* Numeric range format with exclusive bounds and missing value handling */
value age_group
. = 'Missing Age'
low -< 18 = 'Under 18'
18 -< 35 = '18 to 34'
35 -< 65 = '35 to 64'
65 - high = '65 and Older';
run;
4. Storing & Searching Permanent Format Catalogs (LIBRARY=, FMTSEARCH=)
By default, formats created in PROC FORMAT are stored in the temporary catalog WORK.FORMATS and vanish when the SAS session ends. To reuse formats across programs, save them to a permanent library catalog.
Creating Permanent Formats
libname myfmts 'C:\SAS_Formats';
proc format library=myfmts.company_formats;
value $dept_fmt
'HR' = 'Human Resources'
'IT' = 'Information Technology'
'FIN' = 'Finance';
run;
Accessing Permanent Formats with OPTION FMTSEARCH=
When SAS encounters a formatted variable in a DATA step or PROC step, it searches format catalogs in a specific sequence controlled by OPTIONS FMTSEARCH=:
/* Set search order: first check myfmts.company_formats, then WORK.FORMATS */
options fmtsearch=(myfmts.company_formats work);
data work.employee_report;
set work.raw_employees;
format Dept $dept_fmt. ;
run;
Exam Tip:
WORK.FORMATSis always searched first unless explicitly included elsewhere in theFMTSEARCH=list.
5. Catalog Inspection (FMTLIB) & Control Datasets (CNTLIN= / CNTLOUT=)
Inspecting Formats with FMTLIB
The FMTLIB option prints a summary table of all format definitions contained in a catalog to the SAS procedure output, showing range start/end points, labels, and type.
proc format library=work.formats fmtlib;
run;
Creating Formats from Datasets (CNTLIN=) & Exporting (CNTLOUT=)
In large enterprise systems, lookup tables exist as database tables or SAS datasets rather than hardcoded code. PROC FORMAT can build formats dynamically from datasets using CNTLIN= or export catalogs using CNTLOUT=.
Required variables in a CNTLIN= dataset:
FMTNAME: Character string containing the format name (must include$for character formats).START: The starting value or range key.END: The ending value or range key (optional if single value).LABEL: The formatted text string to display.TYPE:'C'for character formats,'N'for numeric formats,'I'for informats.
/* Building a custom format dynamically from a lookup dataset */
/* Dataset work.lookup: FMTNAME='$codefmt', START='US', LABEL='United States', TYPE='C' */
proc format cntlin=work.lookup;
run;
6. Common Pitfalls & Exam Watchouts
- Period Syntax Misplacement: Writing
value $statusfmt. 'A'='Active';insidePROC FORMATgenerates a syntax error. Remove the period! Conversely, writingformat Status $statusfmt;in a DATA step fails to apply the format because the trailing period is missing. - Format Name Ending in a Number: Defining a format named
agefmt1causes a compilation error because format names cannot end in a number. - Missing Format Catalog Error: Opening a dataset that references permanent formats without defining
FMTSEARCH=oroptions nofmterror;producesERROR: Format $DEPT_FMT not found or cannot be loaded.
Which of the following is a valid name for a user-defined character format created in a PROC FORMAT VALUE statement?
$STATEFMT
STATEFMT.
$STATEFMT.
$STATEFMT1
A programmer wants to create a numeric format named AGE_CAT where values from 18 up to but NOT including 30 display as 'Young Adult'. Which range syntax in PROC FORMAT correctly implements this exclusive upper bound?
18 - 30 = 'Young Adult'
18 -< 30 = 'Young Adult'
18 <- 30 = 'Young Adult'
18 <= 30 = 'Young Adult'
A SAS programmer has a lookup table saved as a SAS dataset work.code_lookup containing variables FMTNAME, START, and LABEL. Which PROC FORMAT option uses this dataset to automatically construct user-defined formats without writing hardcoded VALUE statements?
FMTLIB=work.code_lookup
CNTLIN=work.code_lookup
CNTLOUT=work.code_lookup
LIBRARY=work.code_lookup
A SAS DATA step contains the following statement to format the numeric variable Salary:
format Salary dollar12.2 ;
If the programmer later decides to apply a custom numeric format named SALARYFMT created via PROC FORMAT, how should the FORMAT statement be written?
format Salary salaryfmt ;
format Salary $salaryfmt. ;
format Salary salaryfmt. ;
format Salary = salaryfmt() ;
Sections you finish are checked off in the contents.