| OLE DB Programmer's Reference | 
MDPDataset is used to get the cell data for an MDX query specified by pwszQuery, compute the cell data coordinates, and call IMDDataset::GetCellData for each cell in the dataset.
// HRESULT MDPDataset(ICommandText *pICommandText, pwszQuery) {    HRESULT hr;    struct COLUMNDATA    {       SDWORD dwLength;     // length of data (not space allocated)       DBSTATUS dwStatus;   // status of column       VARIANT var;         // variant value    };    // Execute the MDX query.    IMDDataset* pIMDDataset = NULL;    hr = pICommandText->SetCommandText(DBGUID_MDX, pwszQuery);    hr = pICommandText->Execute(NULL, IID_IMDDataset, NULL, NULL,                                (IUnknown **)&pIMDDataset ));    // Fetch the axis info to compute the coordinates.    ULONG cAxis;    MDAXISINFO* rgAxisInfo = NULL;    hr = pIMDDataset->GetAxisInfo( &cAxis, &rgAxisInfo );    // Calculate the coordinate "offset factors". These are used to    // translate from a point in cell space to a set of axis coordinates.    // Example, consider a dataset with three axes and the following    // number of coordinates for each axis:    //   {x,y,z} = {3,4,5}    //      rgAxisOffset[2] = 3*4    //      rgAxisOffset[1] = 3    //      rgAxisOffset[0] = 1    // Thus, where p represents the cell's ordinal value:    //      z = p % 12    //      y = (p - z*12) % 3    //      x = (p - z*12 - y*3)    // And,    //      p = x + 3*y + 12*z    ULONG cAxisTuple;    ULONG iOffset = 1;    ULONG ulMaxCoord = 0;    ULONG rgAxisOffset[MAX_DIMS];   // array of offset multipliers    // For all axes, excluding slicer axis...    for (ULONG iAxis=0; iAxis < cAxis-1; iAxis++)    {       rgAxisOffset[iAxis] = iOffset;       cAxisTuple = rgAxisInfo[iAxis].cCoordinates;       iOffset *= cAxisTuple;    }    ulMaxCoord = iOffset;    ULONG cSliceCoord = rgAxisOffset[cAxis-1]    // Bind to the column values for each cell.    IColumnsInfo *pIColumnsInfo = NULL;    hr = pIMDDataset->QueryInterface(IID_IColumnsInfo,       (void**)&pIColumnsInfo);    ULONG cCol;    WCHAR* pStringsBuffer = NULL;    DBCOLUMNINFO* pInfo = NULL;    hr = pIColumnsInfo->GetColumnInfo(&cCol, &pInfo, &pStringsBuffer);    // Create bindings for each cell's columns, ordered as returned by    // GetColumnInfo. Bind everything as Variant.    dwOffset = 0;    ULONG iBind = 0;    ULONG cBind = 0;    for (ULONG iCol=0; iCol < cCol; iCol++)    {       rgBind[iBind].iOrdinal    = pInfo[iCol].iOrdinal;       rgBind[iBind].obValue     = dwOffset +          offsetof(COLUMNDATA,var);       rgBind[iBind].obLength    = dwOffset +          offsetof(COLUMNDATA,dwLength);       rgBind[iBind].obStatus    = dwOffset +          offsetof(COLUMNDATA,dwStatus);       rgBind[iBind].pTypeInfo   = NULL;       rgBind[iBind].pObject     = NULL;       rgBind[iBind].pBindExt    = NULL;       rgBind[iBind].cbMaxLen    = sizeof(VARIANT);       rgBind[iBind].dwFlags     = 0;       rgBind[iBind].eParamIO    = DBPARAMIO_NOTPARAM;       rgBind[iBind].dwPart      = DBPART_VALUE |                                   DBPART_LENGTH |                                   DBPART_STATUS;       rgBind[iBind].dwMemOwner  = DBMEMOWNER_CLIENTOWNED;       rgBind[iBind].wType       = DBTYPE_VARIANT;       rgBind[iBind].bPrecision  = 0;       rgBind[iBind].bScale      = 0;       dwOffset += rgBind[iBind].cbMaxLen + offsetof(COLUMNDATA,var);       iBind++;    }    cBind = iBind;    // Create the accessor.    IAccessor* pIAccessor;    hr = pIMDDataset->QueryInterface(IID_IAccessor, void**)&pIAccessor);    // Note that the value of dwOffset contains the size of a cell.    // Failure to specify this value will result in an error.    hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBind, rgBind,                                    dwOffset, phAccessor, NULL);    pIAccessor->Release();    pIColumnsInfo->Release();    // Allocate a buffer for a single cell in a slice.    ULONG cbRowsize = dwOffset;    pData = (BYTE*)CoTaskMemAlloc(cbRowSize);    // Fetch each cell in the dataset.    for (ULONG ulCellCoord=0; ulCellCoord < ulMaxCoord; ulCellCoord++)    {       // Populate cell buffer.       hr = pIMDDataset->GetCellData(hAccessor, ulCellCoord, ulCellCoord,                                     pData);       // Traverse each bound cell property value for a single cell "row."       // Use pColumn to access each column's data values.       for (iBind=0; iBind < cBind; iBind++)       {          // Advance to the column value.          (COLUMNDATA*)pColumn = (COLUMNDATA *)(pData +                                  rgBind[iBind].obLength);          // pColumn->var points to the variant value.       }    }    // Free the accessor and rowset.    hr = pIAccessor->ReleaseAccessor(hAccessor, NULL);    hr = pIAccessor->Release();    hr = pIColumnsInfo->Release();    // Free the row data and bindings.    CoTaskMemFree(pData);    CoTaskMemFree(rgBind);    // Free the column info.    CoTaskMemFree(pInfo);    CoTaskMemFree(pwszStringsBuffer);    hr = pIMDDataset->FreeAxisInfo(cAxis, rgAxisInfo);    hr = pIMDDataset->Release();    return hr; } 1998-2001 Microsoft Corporation. All rights reserved.