📄 mapxdataset.cpp
字号:
#include "stdafx.h"
#include "MapXDS.h"
#include "MapXDataset.h"
/////////////////////////////////////////////////////////////////////////////
// CMapXColumnInfoContainer
void CMapXColumnInfoContainer::InitColumns(long nCols)
{
if (cols) {
DestroyColumns();
}
if (nCols) {
m_lCols = nCols;
cols = new IMMapXColumnInfo*[m_lCols];
if( cols==NULL ) throw E_OUTOFMEMORY;
for (long l = 0; l < m_lCols; l++) cols[l] = NULL;
}
}
void CMapXColumnInfoContainer::DestroyColumns()
{
if (cols) {
for (long l = 0; l < m_lCols; l++) if (cols[l]) (cols[l])->Release();
delete [] cols;
}
}
// will throw an HRESULT on failure!
void CMapXColumnInfoContainer::InitColumn(long iNum, BSTR sName, VARTYPE vt, long lColNum)
{
HRESULT hr;
if (iNum < 1 || iNum > (long)m_lCols) return;
if (cols[iNum-1]) cols[iNum-1]->Release();
if( !m_pColumnInfoFactory ) {
hr = CoGetClassObject(CLSID_CMMapXColumnInfo, CLSCTX_ALL, NULL,
IID_IClassFactory, reinterpret_cast<void **>(&m_pColumnInfoFactory));
if( FAILED(hr) ) throw hr;
}
if( !m_pColumnInfoFactory ) throw E_FAIL;
IMMapXColumnInfo* pIMMapXColumnInfo = NULL;
hr = m_pColumnInfoFactory->CreateInstance(NULL, IID_IMMapXColumnInfo,
reinterpret_cast<void **>(&pIMMapXColumnInfo));
if( FAILED(hr) ) throw hr;
if( !m_pColumnInfoFactory ) throw E_FAIL;
hr = pIMMapXColumnInfo->Init(sName, vt, lColNum);
if( FAILED(hr) ) throw hr;
cols[iNum-1] = pIMMapXColumnInfo;
}
CMapXColumnInfoContainer::~CMapXColumnInfoContainer()
{
DestroyColumns();
if( m_pColumnInfoFactory != NULL) m_pColumnInfoFactory->Release();
}
/////////////////////////////////////////////////////////////////////////////
// CMapXSampleDataset
CMapXSampleDataset::CMapXSampleDataset() : CMapXColumnInfoContainer()
{
}
CMapXSampleDataset::~CMapXSampleDataset()
{
}
// IMMapXDataset interface
// TODO: Implement the routines in this interface.
// See IMMapXDataset Interface specification for details.
STDMETHODIMP CMapXSampleDataset::Init(short sType, VARIANT* pvSourceData, VARIANT* pvFields)
{
// TODO: pvSourceData is the gateway to your data. It is the second parameter
// passed to MapX's datasets.Add method. All our data is hardcoded, so we ignore
// it.
HRESULT hrRet = S_OK;
try {
long lNumCols;
if( sType != DATASETENGINE_ID ) throw E_FAIL;
if (pvFields->vt == VT_EMPTY) {
// No fields parameter. Use all columns
long lNumCols = 4;
InitColumns(lNumCols);
for (long l = 1; l <= lNumCols; l++) {
CString strColumnName;
VARTYPE vt;
switch ( l ) {
case 1:
strColumnName = "StateAbbr";
vt = VT_BSTR;
break;
case 2:
strColumnName = "TOTPOPHIS";
vt = VT_I4;
break;
case 3:
strColumnName = "TOTPOPCUR";
vt = VT_I4;
break;
case 4:
strColumnName = "TOTPOPPRO";
vt = VT_I4;
break;
}
BSTR bstrColumnName = strColumnName.AllocSysString();
InitColumn(l, bstrColumnName, vt, l);
::SysFreeString(bstrColumnName);
}
} else if (pvFields->vt & VT_ARRAY) {
short vt = pvFields->vt & ~VT_ARRAY;
VARIANT v;
BSTR *pbstr;
short *pshort;
long *plong;
VARIANT *pvar;
switch (vt) {
case VT_I2:
SafeArrayAccessData(pvFields->parray, (void**)&pshort);
break;
case VT_I4:
SafeArrayAccessData(pvFields->parray, (void **)&plong);
break;
case VT_BSTR:
SafeArrayAccessData(pvFields->parray, (void **)&pbstr);
break;
case VT_VARIANT:
SafeArrayAccessData(pvFields->parray, (void **)&pvar);
break;
}
long lb, ub;
SafeArrayGetLBound(pvFields->parray, 1, &lb);
SafeArrayGetUBound(pvFields->parray, 1, &ub);
lNumCols = ub - lb + 1;
InitColumns(lNumCols);
v.vt = vt;
for (long l = 1; l <= lNumCols; l++) {
long lColNum = 0;
CString strColumnName;
VARTYPE vtColType = VT_EMPTY;
BOOL bGotColumnName = FALSE;
BOOL bGotColumnNumber = FALSE;
// we want the the lth element in the array. Note that both lb and l are 1 based and
// the array is, by dfn, 0 based (hence the - 2)
long lIdx = (lb - 1) + (l - 1);
switch (vt) {
case VT_I2:
lColNum = pshort[lIdx];
bGotColumnNumber = TRUE;
break;
case VT_I4:
lColNum = plong[lIdx];
bGotColumnNumber = TRUE;
break;
case VT_BSTR:
strColumnName = pbstr[lIdx];
bGotColumnName = TRUE;
break;
case VT_VARIANT:
v = pvar[lIdx];
switch( v.vt ) {
case VT_I2:
lColNum = v.iVal;
bGotColumnNumber = TRUE;
break;
case VT_I4:
lColNum = v.lVal;
bGotColumnNumber = TRUE;
break;
case VT_BSTR:
strColumnName = v.bstrVal;
bGotColumnName = TRUE;
break;
}
}
if( bGotColumnName ) {
if( strColumnName.CompareNoCase("StateAbbr") == 0 ) {
vtColType = VT_BSTR;
}
else if( strColumnName.CompareNoCase("TOTPOPHIS") == 0 ){
vtColType = VT_I4;
}
else if( strColumnName.CompareNoCase("TOTPOPCUR") == 0 ){
vtColType = VT_I4;
}
else if( strColumnName.CompareNoCase("TOTPOPPRO") == 0 ){
vtColType = VT_I4;
}
else {
// didn't understand that one, use the first column
// Note that the "right" thing to do might be to ignore this column,
// but since we alread have established the number of fields (and
// this is a sample) we wont do that work.
strColumnName = "StateAbbr";
vtColType = VT_BSTR;
}
}
else if( bGotColumnNumber ) {
switch( lColNum ) {
case 1:
strColumnName = "StateAbbr";
vtColType = VT_BSTR;
break;
case 2:
strColumnName = "TOTPOPHIS";
vtColType = VT_I4;
break;
case 3:
strColumnName = "TOTPOPCUR";
vtColType = VT_I4;
break;
case 4:
strColumnName = "TOTPOPPRO";
vtColType = VT_I4;
break;
default:
// didn't understand that one, use the first column
// Note that the "right" thing to do might be to ignore this column,
// but since we alread have established the number of fields (and
// this is a sample) we wont do that work.
strColumnName = "StateAbbr";
vtColType = VT_BSTR;
break;
}
}
else {
// didn't understand that one, use the first column
// Note that the "right" thing to do might be to ignore this column,
// but since we alread have established the number of fields (and
// this is a sample) we wont do that work.
strColumnName = "StateAbbr";
vtColType = VT_BSTR;
}
BSTR bstrColumnName = strColumnName.AllocSysString();
InitColumn(l, bstrColumnName, vtColType, l);
::SysFreeString(bstrColumnName);
}
SafeArrayUnaccessData(pvFields->parray);
} else {
throw E_FAIL;
}
}
catch (HRESULT hrThrown) {
DestroyColumns();
hrRet = hrThrown;
}
return hrRet;
}
// Our hardcoded sample dataset! Keepin' it simple here...
char* aachStateAbbr[] = {
"AL","AK","AZ","AR","CA","CO","CT","DE","DC","FL","GA","HI","ID","IL","IN","IA","KS","KY",
"LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH",
"OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"
};
long alTOTPOPHIS[] = {
4040587,550043,3665228,2350725,29760022,3294394,3287116,666168,606900,
12937926,6478216,1108229,1006749,1430602,5544159,2776755,2477574,3685296,
4219973,1227928,4781468,6016425,9295297,4375099,2573216,5117073,799065,
1578385,1201833,1109252,7730188,1515069,17990456,6628637,638800,10847115,
3145585,2842321,11881643,1003464,3486703,696004,4877185,16986510,1722850,
562758,6187358,4866692,1793477,4891769,453588
};
long alTOTPOPCUR[] = {
221932,610350,4000398,2441646,31546602,3630585,3275195,707864,571592,13849741,
7020384,1186692,1120679,11760900,5752928,2823048,2543745,3814122,4313195,
1241451,5008060,6012972,9521288,4550733,2659929,5262100,848637,1613762,
1431731,1129184,7915280,1640014,18248700,7019142,634353,11149084,3251236,
3076269,12088344,999362,3678846,719616,5151582,18276706,1892307,579094,6563063,
5345474,1826545,5072574,473863
};
long alTOTPOPPRO[] = {
4455517,679683,4452859,2566937,33575312,4079905,3261723,757702,530751,14933526,
7713623,1278719,1270278,12177648,6017915,2880078,2625638,3981255,4419968,1256627,
5278406,6041000,9784220,4778419,2778826,5453966,918241,1653501,1709870,1162664,
8167263,1801827,18609072,7523251,632308,11518533,3382648,3370702,12348519,994282,
3904256,751132,5504280,19931518,2114834,600595,7040419,5932630,1872266,5298193,
499094
};
STDMETHODIMP CMapXSampleDataset::GetSample(long lColNum, long lNumSampleValuesRequested, VARTYPE vtRequested, VARIANT * pvarData, long * pNumRecordsFetched)
{
long nCount=0;
SAFEARRAY FAR* psa=NULL;
if( lNumSampleValuesRequested >= (sizeof(aachStateAbbr) / sizeof(aachStateAbbr[0])) ) {
lNumSampleValuesRequested = sizeof(aachStateAbbr) / sizeof(aachStateAbbr[0]);
}
try {
IMMapXColumnInfo* pIMMapXColumnInfo;
HRESULT hr = GetColumnInfoByIndex( lColNum, &pIMMapXColumnInfo);
if( FAILED(hr) ) throw hr;
CComBSTR bstrColumnName;
hr = pIMMapXColumnInfo->GetName(&bstrColumnName);
if( FAILED(hr) ) throw hr;
pIMMapXColumnInfo->Release();
CString strColumnName = bstrColumnName;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 1;
rgsabound[0].cElements = lNumSampleValuesRequested;
psa = SafeArrayCreate(vtRequested, 1, rgsabound);
if(psa == NULL){
*pNumRecordsFetched = 0;
return E_OUTOFMEMORY;
}
for(int iRows=0;iRows<lNumSampleValuesRequested;iRows++) {
nCount++;
switch (vtRequested) {
// TODO: we cheat here because we know that currently MapX
// will ask for only doubles or BSTR's. You shouldn't.
case VT_R8: {
double dTmp;
if( strColumnName.CompareNoCase("StateAbbr") == 0 ){
dTmp = 0.0;
}
else if( strColumnName.CompareNoCase("TOTPOPHIS") == 0 ){
dTmp = alTOTPOPHIS[iRows];
}
else if( strColumnName.CompareNoCase("TOTPOPCUR") == 0 ){
dTmp = alTOTPOPCUR[iRows];
}
else if( strColumnName.CompareNoCase("TOTPOPPRO") == 0 ){
dTmp = alTOTPOPPRO[iRows];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -