DDEを用いてExcelのセルの読み込み・書き込みをする。(32/64bit)

icon 項目のみ表示/展開表示の切り替え

概要

DDEを使いExcelファイル(Excel 2010β)よりセルを読み込みセルに書き出すプログラムです。

起動後、メニュよりDDEデモ(D) データの読み込み・書き込み(S)を選択すると上記ダイアログボックスが表示されExcelファイル名・シート名、読み込みセルの範囲、書き込みセルおよび内容を入力してOKを押すとExcelが起動し、本プログラムのウィンドウにExcelのシートの内容が表示されます。またExcelには書き込みセルで指定した場所に書き込み内容が反映されます。

dde.cpp

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <stdio.h>
#include <tchar.h>
#include "resource.h"



HDDEDATA CALLBACK DdemlCallback(UINT, UINT, HCONV, HSZ, HSZ,HDDEDATA, ULONG_PTR, ULONG_PTR);
LRESULT CALLBACK inDlgProc(HWND, UINT, WPARAM, LPARAM);

BOOL InitApp(HINSTANCE);        //      ウィンドウクラス登録
BOOL InitInstance(HINSTANCE, int);      //      メインウィンドウ作成
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int DDE_INIT(HWND);                     //      DDE初期化  
int DDE_CONNECT(HWND);          //      ファイル・シートに接続
int DDE_DISCONNECT(HWND);       //      ファイル・シートと切断
int DDE_SetData(HWND);  //      セル書き込み
int DDE_GetData(HWND);          //      セル読み込み
bool cells(TCHAR* a1,int* r,int* c);    // EXCELで使用するA1形式のセル番地をRC系列に変換する
void colmn_set(int x,TCHAR* s); //      列番号よりA1形式の列名を得る。 
bool Excel_Set_Cell(DWORD ddeInst,HCONV hConv2,int r,int c,TCHAR* write_data);  //      Excelのセルに書き込む
bool Excel_Get_Cell(DWORD ddeInst,HCONV hConv2,int r,int c,TCHAR* szData,int sz);       //      Excelのセルを読み込む

HINSTANCE hInst;        //      アプリケーションインスタンス
TCHAR szClassName[] = TEXT("dde_test");        //ウィンドウクラス
DWORD ddeInst=0;                        //      インタンス
HSZ hszService;                         //      
HSZ hszTopic1;                          //      ファイル名文字列ハンドル
HSZ hszTopic2;                          //      シート名文字列ハンドル
HCONV hConv1;                           //      ファイル名へのハンドル
HCONV hConv2;                           //      シート名へのハンドル
TCHAR fname[MAX_PATH];          //      Excel ファイル名
TCHAR sname[32];                        //      Excel シート名
TCHAR read_cell_top[32];        //      読み込みセル左上
TCHAR read_cell_bottom[32];     //      読み込みセル右下
TCHAR write_cell[32];           //      書き込みセル
TCHAR write_data[64];           //      書き込み内容
HWND hList;                                     //      リストビューハンドル


int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,LPSTR lpsCmdLine, int nCmdShow){
    MSG msg;
    
    if (!InitApp(hCurInst))
        return FALSE;
    if (!InitInstance(hCurInst, nCmdShow)) 
        return FALSE;
        BOOL b;
    while ((b=GetMessage(&msg, NULL, 0, 0))!=0) {
                if(b==-1)       //      エラー時に無限ループにならないようにする
                        break;
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}


BOOL InitApp(HINSTANCE hInst){
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = TEXT("DDEMENU");
    wc.lpszClassName = (TCHAR*)szClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    return (RegisterClassEx(&wc));
}


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){
    HWND hWnd;
    hInst = hInstance;

    hWnd = CreateWindow(szClassName,
            TEXT("DDE Excel Demo"),
            WS_OVERLAPPEDWINDOW, 
            CW_USEDEFAULT, 
            CW_USEDEFAULT, 
                        CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL, 
            hInstance,   
            NULL);
    if (!hWnd)
        return FALSE;
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
        int h;
        int col_max;
        int x;
        TCHAR buf[64];
    switch (msg) {
                case WM_CREATE:
                        hList = CreateWindowEx(0,
              WC_LISTVIEW, TEXT(""),
               WS_CHILD | WS_VISIBLE | LVS_REPORT,
               0, 0, 0, 0,
               hWnd,
               (HMENU)ID_LISTVIEW,
               hInst,
               NULL);
                        read_cell_top[0]=read_cell_bottom[0]=fname[0]=sname[0]=_T('\0');
                        break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                case IDM_END:
                    SendMessage(hWnd, WM_CLOSE, 0, 0);
                    break;
                case IDM_START:
                                        if(DialogBox(hInst, TEXT("INDLG"), hWnd, (DLGPROC)inDlgProc)==IDOK){
                                                if((h=(int)ShellExecute(hWnd,TEXT("open"),fname,TEXT(""),TEXT(""),SW_SHOW))<=32){
                                                        _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),TEXT("ShellExecute APIでエラーが発生しました。(0x%x)"),h);

                                                        MessageBox(hWnd, buf, TEXT("エラー"), MB_OK | MB_ICONERROR);
                                                        break;
                                                }
                                                SendMessage(hList,LVM_DELETEALLITEMS,0,0);
                                                col_max=(int)SendMessage(ListView_GetHeader(hList),HDM_GETITEMCOUNT,0,0);
                                                for(x=0;x<col_max;x++){
                                                        ListView_DeleteColumn(hList, 0);
                                                }
                                                if(ddeInst==0)
                                                        DDE_INIT(hWnd);
                                                DDE_CONNECT(hWnd);
                                                DDE_GetData(hWnd);
                                                DDE_SetData(hWnd);
                                                DDE_DISCONNECT(hWnd);
                                        }
                                        break;
            }
                break;
            case WM_SIZE:
                        MoveWindow(hList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
                        break;
        case WM_CLOSE:
            DestroyWindow(hWnd);
            break;
        case WM_DESTROY:
                        if(ddeInst)
                                if(DdeUninitialize(ddeInst) == 0)
                                        MessageBox(hWnd, TEXT("DdeUninitialize"),TEXT( "エラー"), MB_OK | MB_ICONERROR);            PostQuitMessage(0);

            break;
        default:
            return (DefWindowProc(hWnd, msg, wParam, lParam));
    }
    return 0;
}

int DDE_INIT(HWND hWnd){
        TCHAR buf[64];
        UINT ret;
    if((ret=DdeInitialize(&ddeInst, DdemlCallback, APPCMD_CLIENTONLY, 0)) != DMLERR_NO_ERROR){
                _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),TEXT("DdeInitialize APIでエラーが発生しました。(0x%x)"),ret);
        MessageBox(hWnd, buf, TEXT("エラー"), MB_OK | MB_ICONERROR);
        return -1;
    }
    return 0;
}

int DDE_CONNECT(HWND hWnd){
        UINT ret;
        TCHAR buf[64];
#ifdef UNICODE
    hszService = DdeCreateStringHandle(ddeInst, TEXT("Excel"), CP_WINUNICODE);
    hszTopic1 = DdeCreateStringHandle(ddeInst, fname, CP_WINUNICODE);
    hszTopic2 = DdeCreateStringHandle(ddeInst, sname, CP_WINUNICODE);
#else
        hszService = DdeCreateStringHandle(ddeInst, TEXT("Excel"), CP_WINANSI);
    hszTopic1 = DdeCreateStringHandle(ddeInst, fname, CP_WINANSI);
    hszTopic2 = DdeCreateStringHandle(ddeInst, sname, CP_WINANSI);
#endif
        hConv1 = DdeConnect(ddeInst, hszService, hszTopic1, NULL);
    if ((ret=DdeGetLastError(ddeInst)) != DMLERR_NO_ERROR) {
                _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),TEXT("DdeConnect(ブック) APIでエラーが発生しました。(0x%x)"),ret);
        MessageBox(0, buf, TEXT("エラー"), MB_OK | MB_ICONERROR);
        return -1;
    }
        hConv2 = DdeConnect(ddeInst, hszService, hszTopic2, NULL);
    if ((ret=DdeGetLastError(ddeInst)) != DMLERR_NO_ERROR) {
                _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),TEXT("DdeConnect(シート) APIでエラーが発生しました。(0x%x)"),ret);
        MessageBox(0, buf, TEXT("エラー"), MB_OK | MB_ICONERROR);
        return -2;
    }
        return 0;
}

int DDE_DISCONNECT(HWND hWnd){
        UINT ret;
        TCHAR buf[64];
    if (hConv1){
        if(DdeFreeStringHandle(ddeInst, hszService) == 0)
            MessageBox(hWnd, TEXT("DdeFreeStringHandle(Excel)"), TEXT("エラー"), MB_OK);
        if(DdeFreeStringHandle(ddeInst, hszTopic1) == 0)
            MessageBox(hWnd, TEXT("DdeFreeStringHandle(ブック)"), TEXT("エラー"), MB_OK);
        if(DdeFreeStringHandle(ddeInst, hszTopic2) == 0)
            MessageBox(hWnd, TEXT("DdeFreeStringHandle(シート)"), TEXT("エラー"), MB_OK);
                if(DdeDisconnect(hConv1) == 0){
                        ret=DdeGetLastError(ddeInst);
                        _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),TEXT("DdeDisconnect(ブック) APIでエラーが発生しました。(0x%x)"),ret);
                        MessageBox(hWnd, buf, TEXT("エラー"), MB_OK | MB_ICONERROR);
                }
                if(DdeDisconnect(hConv2) == 0){
                        ret=DdeGetLastError(ddeInst);
                        _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),TEXT("DdeDisconnect(シート) APIでエラーが発生しました。(0x%x)"),ret);
                        MessageBox(hWnd, buf, TEXT("エラー"), MB_OK | MB_ICONERROR);
                }
        hConv1 = 0;
                hConv2 = 0;
    }
    return 0;
}

bool Excel_Set_Cell(DWORD ddeInst,HCONV hConv2,int r,int c,TCHAR* write_data){
        TCHAR write_cell[16];
    HSZ hszMyTopic;
        HDDEDATA hRet;
        UINT err;
        TCHAR buf[64];

        _stprintf_s(write_cell,sizeof(write_cell)/sizeof(TCHAR),TEXT("R%iC%i"),r,c);
#if     UNICODE
        hszMyTopic = DdeCreateStringHandle(ddeInst, write_cell, CP_WINUNICODE);
    hRet = DdeClientTransaction(
        (LPBYTE)write_data,
        int(_tcslen(write_data)+1)*sizeof(TCHAR) ,
        hConv2,
        hszMyTopic,
        CF_UNICODETEXT, 
        XTYP_POKE,
        10000,
        NULL);
#else
        hszMyTopic = DdeCreateStringHandle(ddeInst, write_cell, CP_WINANSI);
    hRet = DdeClientTransaction(
        (LPBYTE)write_data,
        int(_tcslen(write_data)+1),
        hConv2,
        hszMyTopic,
        CF_TEXT,
        XTYP_POKE,
        10000,
        NULL);
#endif
    
    if(!hRet && (err=DdeGetLastError(ddeInst)) != DMLERR_NO_ERROR){
                _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),TEXT("DdeClientTransaction(XTYP_POKE) %s %s %x"),write_cell,write_data,err);
        MessageBox(0, buf, TEXT("エラー"), MB_OK);
        return false;
    }else if (hRet) {
        DdeFreeStringHandle(ddeInst, hszMyTopic);
        DdeFreeDataHandle(hRet);
    }
        return true;
}

int DDE_SetData(HWND hWnd){
        int r,c;
    if (!hConv1){
        MessageBox(hWnd, TEXT("DdeInitializeが呼び出されていないかエラーが発生しております"), TEXT("エラー"), MB_OK | MB_ICONERROR);
        return -1;
    }
        cells(write_cell,&r,&c);
        Excel_Set_Cell(ddeInst,hConv2,r,c,write_data);

        return 0;
}

bool Excel_Get_Cell(DWORD ddeInst,HCONV hConv2,int r,int c,TCHAR* szData,int sz){
    HDDEDATA hRet;
    HSZ hszMyTopic;
        TCHAR szBuf[16];
        UINT err;
        TCHAR buf[64];
        _stprintf_s(szBuf,sizeof(szBuf)/sizeof(TCHAR),TEXT("R%iC%i"),r,c);
#ifdef UNICODE
        hszMyTopic = DdeCreateStringHandle(ddeInst, szBuf, CP_WINUNICODE);
        hRet = DdeClientTransaction(NULL, 0, hConv2, hszMyTopic,        CF_UNICODETEXT, XTYP_REQUEST,1000,      NULL);
#else
        hszMyTopic = DdeCreateStringHandle(ddeInst, szBuf, CP_WINANSI);
        hRet = DdeClientTransaction(NULL, 0, hConv2, hszMyTopic,        CF_TEXT,XTYP_REQUEST,1000,      NULL);
#endif
        if(!hRet && (err=DdeGetLastError(ddeInst)) != DMLERR_NO_ERROR){
                _stprintf_s(buf,sz,TEXT("DdeClientTransaction(XTYP_REQUEST) %s 0x%x"),szBuf,err);
                MessageBox(0 , buf,TEXT( "エラー"), MB_OK);
                return false;
        }else if (hRet){
                DdeGetData(hRet, (LPBYTE)szData, sz, 0);
                DdeFreeStringHandle(ddeInst, hszMyTopic);
                DdeFreeDataHandle(hRet);
        }
        return true;
}


int DDE_GetData(HWND hWnd){
        LV_ITEM item;
        int x,y;
        int col_max=0;
        TCHAR szBuf[64];
        TCHAR szData[64];
    if(!hConv1){
        MessageBox(hWnd, TEXT("DdeInitializeが呼び出されていないかエラーが発生しております"), TEXT("エラー"), MB_OK | MB_ICONERROR);
        return -1;
    }
        int top_x,top_y;
        int bottom_x,bottom_y;
        cells(read_cell_top  , &top_y, &top_x);
        cells(read_cell_bottom, &bottom_y, &bottom_x);
        LV_COLUMN lvcol;
        lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
    lvcol.fmt = LVCFMT_LEFT;
    lvcol.cx = 64;
    lvcol.pszText = TEXT("行・列");
    lvcol.iSubItem = 0;
    ListView_InsertColumn(hList,0 , &lvcol);

        for(x=top_x;x<=bottom_x;x++){
                colmn_set(x,szBuf);
        lvcol.pszText = szBuf;
        lvcol.iSubItem = x - top_x+1;
        ListView_InsertColumn(hList,x - top_x+1 , &lvcol);
        }
        for(y=top_y;y<=bottom_y;y++){
                _stprintf_s(szBuf,sizeof(szBuf)/sizeof(TCHAR),TEXT("%i"),y);
                item.mask = LVIF_TEXT  | LVIF_PARAM;
                item.pszText = szBuf;
                item.iItem = y-top_y;
                item.iSubItem = 0;
                item.lParam = y-top_y;
                ListView_InsertItem(hList, &item);
                for(x=top_x;x<=bottom_x;x++){
                        Excel_Get_Cell(ddeInst,hConv2,y,x,szData,sizeof(szData)/sizeof(TCHAR));
                        item.mask = LVIF_TEXT;
                        item.pszText = szData;
                        item.iItem = y - top_y;
                        item.iSubItem = x - top_x+1;
                        ListView_SetItem(hList, &item);
                }
        }
    return 0;
}

LRESULT CALLBACK inDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
        OPENFILENAME o;
    switch (msg) {
                case WM_INITDIALOG:
                        SetWindowText(GetDlgItem(hDlg, IDC_EDIT1),read_cell_top);
                        SetWindowText(GetDlgItem(hDlg, IDC_EDIT2),read_cell_bottom);
                        SetWindowText(GetDlgItem(hDlg, IDC_EDIT3),fname);
                        SetWindowText(GetDlgItem(hDlg, IDC_EDIT4),sname);
                        SetWindowText(GetDlgItem(hDlg, IDC_EDIT5),write_cell);
                        SetWindowText(GetDlgItem(hDlg, IDC_EDIT6),write_data);
                        
                        break;
        case WM_COMMAND:
            switch (LOWORD(wParam)){
                case IDOK:
                    Edit_GetText(GetDlgItem(hDlg, IDC_EDIT1), read_cell_top, sizeof(read_cell_top)/sizeof(TCHAR));
                    Edit_GetText(GetDlgItem(hDlg, IDC_EDIT2), read_cell_bottom, sizeof(read_cell_bottom)/sizeof(TCHAR));
                    Edit_GetText(GetDlgItem(hDlg, IDC_EDIT3), fname, sizeof(fname)/sizeof(TCHAR));
                    Edit_GetText(GetDlgItem(hDlg, IDC_EDIT4), sname, sizeof(sname)/sizeof(TCHAR));
                    Edit_GetText(GetDlgItem(hDlg, IDC_EDIT5), write_cell, sizeof(write_cell)/sizeof(TCHAR));
                    Edit_GetText(GetDlgItem(hDlg, IDC_EDIT6), write_data, sizeof(write_data)/sizeof(TCHAR));
                    EndDialog(hDlg, IDOK);
                    return TRUE;
                                case IDC_REF:
                                        ZeroMemory(&o,sizeof(o));
                                        o.lStructSize=sizeof(o);
                                        o.Flags=0;
                                        o.Flags |= OFN_HIDEREADONLY;
                                        o.lpstrFile=fname;
                                        o.nMaxFile=sizeof(fname)/sizeof(TCHAR);
                                        o.lpstrFilter=TEXT("xls\0\0");
                                        o.nFilterIndex=1;
                                        if(GetOpenFileName(&o)){
                                                SetWindowText(GetDlgItem(hDlg, IDC_EDIT3),fname);
                                        }
                                        break;

                case IDCANCEL:
                    EndDialog(hDlg, IDCANCEL);
                    return TRUE;
            }
            break;
    }
    return FALSE;
}


HDDEDATA CALLBACK DdemlCallback(UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hdata, ULONG_PTR dwData1, ULONG_PTR dwData2){

    return (HDDEDATA)NULL;
}


// EXCELで使用するA1形式のセル番地をRC系列に変換する        


bool cells(TCHAR* a1,int* r,int* c){
        TCHAR* p=a1;
        *c=0;
        *r=0;
        TCHAR ch;
        int t;
        while(*p){
                ch=*p;
                if(_istupper(*p)){
                        t = ch - _T('A')+1;
                        *c = *c * 26 + t;
                }else if(_istdigit(*p)){

                        t = ch - _T('0');
                        *r = *r * 10 + t;
                }else{
                        return false;
                }
                ++p;
        }
        if(256<*c)
                return false;

        return true;

}

//      列番号よりA1形式の列名を得る。 

void colmn_set(int x,TCHAR* s){
        int t1=x/26;
        int t2=x % 26;
        TCHAR* p=s;
        if(t1>=1){
                *p=_T('A')+t1-1;
                ++p;
        }
        *p=_T('A')+t2-1;
        ++p;
        *p=_T('\0');
}

resource.h

#define IDM_END    100
#define IDM_START       110

#define IDC_STATIC      200
#define IDC_STATIC2     220
#define IDC_STATIC3     230
#define IDC_STATIC4     240
#define IDC_STATIC5     250
#define IDC_STATIC6     260
#define IDC_EDIT1       310
#define IDC_EDIT2       320
#define IDC_EDIT3       330
#define IDC_EDIT4       340
#define IDC_EDIT5       350
#define IDC_EDIT6       360
#define IDC_FILENAME    370
#define IDC_REF 380


#define ID_LISTVIEW 400

 

dde.rc

#include <windows.h>
#include "resource.h"

DDEMENU MENU 
BEGIN
    POPUP "DDEデモ(&D)"
    BEGIN
        MENUITEM "データの読み込み・書き込み(&S)",                  IDM_START
        MENUITEM "プログラムの終了(&X)",                IDM_END
    END
END



INDLG DIALOGEX 0, 0, 375, 179
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Excel データ読み込み・書き込み"
FONT 9, "MS Pゴシック", 0, 0, 0x0
BEGIN
    LTEXT           "ファイル名",IDC_STATIC3,9,9,31,8
    EDITTEXT        IDC_EDIT3,15,19,293,12,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "参照",IDC_REF,328,19,35,14
    LTEXT           "シート名",IDC_STATIC4,9,35,26,8
    EDITTEXT        IDC_EDIT4,15,45,293,12,ES_AUTOHSCROLL
    LTEXT           "読み取り範囲",IDC_STATIC,9,69,28,8
    EDITTEXT        IDC_EDIT1,15,79,32,12,ES_AUTOHSCROLL
    LTEXT           "~",IDC_STATIC2,55,79,8,8
    EDITTEXT        IDC_EDIT2,75,79,32,12,ES_AUTOHSCROLL

    LTEXT           "書き込みセル",IDC_STATIC5,9,95,48,8
    EDITTEXT        IDC_EDIT5,15,105,22,12,ES_AUTOHSCROLL
    LTEXT           "書き込み内容",IDC_STATIC6,9,124,48,8
    EDITTEXT        IDC_EDIT6,15,134,32,12,ES_AUTOHSCROLL

        
        
        DEFPUSHBUTTON   "OK",IDOK,250,154,50,14
    PUSHBUTTON      "キャンセル",IDCANCEL,311,154,50,14
        
END