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 ($18 \le x \le 29$) |
Exclusive Bounds (<) | 18 -< 30 = '18 to 29' <br> 30 <- 50 = '31 to 50' | 18 -< 30 ($18 \le x < 30$)<br>30 <- 50 ($30 < x \le 50$) |
| Open-Ended Keywords | LOW - 17 = 'Minor' <br> 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?
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?
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?
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?