Overriding Formats for Input Operations

How to Override Default Formats

In a SAS data set, a variable (column) can have persisted formatting information, which you have the option to override. To override the persisted (default) format values, you specify a format length (width) and number of decimals (for numeric formats).

Sample Code for Overriding Default Formats

The example data set has three columns: SALEDATE, QUANTITY, and PRICE. Each column has a persisted (default) format. You want to override the default formatting for the SALEDATE and PRICE columns. Specifically, you want to format the SALEDATE column using MMDDYY8. formatting, and you want to format the PRICE column using DOLLAR8.2.
You also want to perform some calculations on the PRICE column. To perform the calculations, you must write additional code that binds PRICE as a numeric value. So, even though the data set has only three columns, this example requires the following four bindings:
  • SALEDATE bound as DBTYPE_BSTR with MMDDYY8. formatting
  • QUANTITY bound as a DBTYPE_R8
  • PRICE bound as DBTYPE_BSTR with DOLLAR8.2 formatting
  • PRICE bound as DBTYPE_R8
DBBINDING rgBindings[4]; 1
DBBINDEXT rgBindingExtensions[2]; 
SASFORMAT rgFormatOverrides[2];  


ULONG dwOffset; 2


typedef struct 3
{ 
DWORD status; 
BYTE value[1];
} COLUMNDEF;


memset( rgBindings, 0, sizeof( rgBindings ) ); 4
memset( rgBindingExtensions, 0, sizeof( rgBindingExtensions ) );
memset( rgFormatOverrides, 0, sizeof( rgFormatOverrides ) ); 


dwOffset = 0; 5


rgBindings[0].iOrdinal = 1; 6
rgBindings[0].dwPart = DBPART_VALUE | DBPART_STATUS;
rgBindings[0].obValue =dwOffset + offsetof( COLUMNDEF, value );
rgBindings[0].obStatus =dwOffset + offsetof( COLUMNDEF, status );
rgBindings[0].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
rgBindings[0].wType = DBTYPE_BSTR;


rgFormatOverrides[0].wType = SASFMT_FORMAT; 7
rgFormatOverrides[0].pwszName = L"MMYYDD";
rgFormatOverrides[0].iLength = 8; 


rgBindingExtensions[0].pExtension = (BYTE *) &(rgFormatOverrides[0]); 8
rgBindingExtensions[0].ulExtension = 1;
rgBindings[0].pBindExt = &(rgBindingExtensions[0]);


dwOffset += sizeof(BSTR) + offsetof( COLUMNDATA, value ); 9


rgBindings[1].iOrdinal = 2; 10
rgBindings[1].dwPart = DBPART_VALUE | DBPART_STATUS;
rgBindings[1].obValue =dwOffset + offsetof( COLUMNDEF, value );
rgBindings[1].obStatus =dwOffset + offsetof( COLUMNDEF, status );
rgBindings[1].wType = DBTYPE_R8;
dwOffset += sizeof(double) + offsetof( COLUMNDATA, value ); 


rgBindings[2].iOrdinal = 3; 11
rgBindings[2].dwPart = DBPART_VALUE | DBPART_STATUS;
rgBindings[2].obValue =dwOffset + offsetof( COLUMNDEF, value );
rgBindings[2].obStatus =dwOffset + offsetof( COLUMNDEF, status );
rgBindings[2].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
rgBindings[2].wType = DBTYPE_BSTR;

rgFormatOverrides[1].wType = SASFMT_FORMAT;
rgFormatOverrides[1].pwszName = L"DOLLAR";
rgFormatOverrides[1].iLength = 8;
rgFormatOverrides[1].iDecimals = 2;

rgBindingExtensions[1].pExtension = (BYTE *) &(rgFormatOverrides[0]);
rgBindingExtensions[1].ulExtension = 1;
rgBindings[2].pBindExt = &(rgBindingExtensions[0]);
dwOffset += sizeof(BSTR) + offsetof( COLUMNDATA, value );


rgBindings[3].iOrdinal = 3; 12
rgBindings[3].dwPart = DBPART_VALUE | DBPART_STATUS;
rgBindings[3].obValue =dwOffset + offsetof( COLUMNDEF, value );
rgBindings[3].obStatus =dwOffset + offsetof( COLUMNDEF, status );
rgBindings[3].wType = DBTYPE_R8;


dwOffset += sizeof(double) + offsetof( COLUMNDATA, value ); 13
1creates an array of DBBINDING structures. There are four bindings, two of which have formatting overrides.
2tracks the offset of a bound data point into an I/O buffer.
3After each binding is created, lays out a status and value part.
4As a matter of good programming, all structures are initialized.
5Parts are laid into the buffer at offset 0. When the bindings are created, dwOffset is the total number of bytes that are needed to hold one row in memory.
6binds SALEDATE as DBTYPE_BSTR with the MMYYDD8. format applied. The basic OLE DB binding information comes first.
7prepares the format override for SALEDATE.
8links the SASFORMAT structure to the DBBINDING structure.
9sets the offset to increase beyond the data points for SALEDATE.
10binds QUANTITY as DBTYPE_R8. Only basic OLE DB binding information is needed.
11binds PRICE as DBTYPE_BSTR with the DOLLAR8.2 format applied. This action is similar to the binding for SALEDATE.
12binds PRICE as DBTYPE_R8.
13After this code is executed, dwOffset is the number of bytes that the application needs in order to store a row of data that is retrieved by using this binding information.