In a SAS data set, a variable (column) can have persisted formatting information. If persisted information exists, then the simplest way to format data is to request that a column of data be returned with its default format. If there is no persisted format information, then a "best fit" strategy, based on the variable type, is used.
Note: You also can override the default format.
Follow these steps to request the default format.
Follow these steps to create a DBBINDEXT structure, an OLE DB-defined structure that is used to associate a SASFORMAT structure with a DBBINDING structure.
Follow these steps to complete the process. You will use your DBBINDING structure.
The provider will return data for this column with the applied default format, using your specified OLE DB type to physically represent the data in memory.
The example data set has three columns: SALEDATE, QUANTITY, and PRICE. The objective is to obtain all three of these columns using the default format associated with each. To do this, the default formats are specified when you write code to bind each column.
A SASFORMAT structure is created to request the default format. The same instance of this structure can be reused for all three columns.
#include "SASExtensions.h" // Required for SAS extensions to OLE DB // (that is, to define the SASFORMAT structure)
SASFORMAT formatOverride;
All members are initialized to NULL or zero.
memset( &formatOverride, 0, sizeof( formatOverride ) );
The override type is set to "formatting".
formatOverride.wType = SASFMT_FORMAT;
A DBBINDEXT structure is created to link the SASFORMAT structure to the DBBINDING structures. Again, the DBBINDEXT structure is reused for all three columns.
DBBINDEXT bindingExtension;
bindingExtension.pExtension = (BYTE *) &formatOverride; bindingExtension.ulExtension = 1;
The bindingExtension is tied to each column that will be formatted. Because three columns will be bound, the example uses three DBBINDING structures.
DBBINDING rgBindings[3]; // Provides instruction on how to organize // the data returned by the provider.
struct ACOLUMN { DWORDstatus; BSTRvalue; };
As a matter of good programming, the structure is initialized, too.
memset( rgBindings, 0, sizeof( rgBindings ) );
The following loop binds all the columns as DBTYPE_BSTR and applies the default format as specified by the SASFORMAT structure.
for( ULONG i =0; i < sizeof(rgBindings); i++) { // Columns are bound in order, skipping the self bookmark since it can't be formatted
The column length is not returned because the data is being returned as BSTR, which has a fixed length. The status is returned because applying a format to a particular data item could fail.
rgBindings[i].iOrdinal = i+1;
rgBindings[i].dwPart = DBPART_VALUE | DBPART_STATUS; rgBindings[i].obValue = (i * sizeof(struct ACOLUMN)) + offsetof(struct ACOLUMN, value); rgBindings[i].obStatus = (i * sizeof(struct ACOLUMN)) + offsetof(struct ACOLUMN, status);
Each data item is freed as the client finishes with it.
rgBindings[i].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
The default character type is accepted. If you use a different character type, you must specify a maximum column width. The value would be based on the width of the format being applied.
rgBindings[i].wType =
The formatting information is supplied. You can reuse the same DBBINDEXT and SASFORMAT structure multiple times to use the default format.
DBTYPE_BSTR; rgBindings[i].pBindExt = &bindingExtension; }
With such an array of DBBINDING structures, a call can be made to IAccessor::CreateAccessor to create an HACCESSOR that will obtain columns using SAS formats.