// マルチバイト
#include <Windows.h>
#include <CommCtrl.h>
#include <sqlext.h>
#include <tchar.h>
#include <vector>
#include <string>
#include "resource.h"
#define DRIVER _T("Microsoft Text Driver (*.txt; *.csv)")
#define DATABASE _T("C:\\tmp")
#define TABLE _T("09TOCHIG.CSV")
#define TABLE2 _T("09TOCHIG_.CSV")
// 型定義
struct ColInfo { // 列情報
std::string strName; // 列名
SQLSMALLINT datatype; // データ型
};
typedef std::vector<ColInfo> VecCI;
// 関数プロトタイプ宣言
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnInitDialog(HWND hDlg);
void LoadTable(HWND hDlg);
BOOL SaveTable(HWND hDlg);
// 外部変数構造体
static struct {
HWND hList; // リストビュー
SQLHENV henv; // 環境ハンドル
SQLHDBC hdbc; // 接続ハンドル
VecCI vecci; // 列情報
} g;
//==============================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
// ODBC環境ハンドルの確保
SQLRETURN rc; // retcode
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &g.henv);
rc = SQLSetEnvAttr(g.henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc);
SQLFreeHandle(SQL_HANDLE_ENV, g.henv);
return 0;
}
//------------------------------------------------------------------------------
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
INT_PTR nRet = TRUE; // メッセージを処理した
switch (uMsg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_SAVE:
if (SaveTable(hDlg)) {
MessageBox(hDlg, _T("完了しました。"), _T("報告"), MB_OK);
}
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
}
break;
case WM_INITDIALOG:
OnInitDialog(hDlg);
nRet = TRUE; // SetFocusでフォーカスを設定した場合はFALSE
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_DESTROY:
SQLDisconnect(g.hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, g.hdbc);
break;
default:
nRet = FALSE; // メッセージを処理しなかった
}
return nRet;
}
//------------------------------------------------------------------------------
void OnInitDialog(HWND hDlg)
{
// リストビュー拡張スタイル
g.hList = GetDlgItem(hDlg, IDC_LIST);
DWORD dwExStyle = ListView_GetExtendedListViewStyle(g.hList);
dwExStyle |= LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
ListView_SetExtendedListViewStyle(g.hList, dwExStyle);
// テーブルの読み込み
LoadTable(hDlg);
}
//------------------------------------------------------------------------------
void LoadTable(HWND hDlg)
{
SQLHSTMT hstmt; // 命令ハンドル
SQLSMALLINT col;
SQLSMALLINT n;
SQLSMALLINT datatype;
TCHAR buf[256];
SQLLEN len;
SQLRETURN rc; // retcode
// データベースへの接続
rc = SQLAllocHandle(SQL_HANDLE_DBC, g.henv, &g.hdbc);
rc = SQLDriverConnect(g.hdbc, NULL,
(SQLTCHAR *) TEXT("driver={") DRIVER TEXT("}; dbq=") DATABASE,
SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
if (!SQL_SUCCEEDED(rc)) {
return;
}
// 検索
rc = SQLAllocHandle(SQL_HANDLE_STMT, g.hdbc, &hstmt);
rc = SQLExecDirect(hstmt, (SQLTCHAR *) TEXT("select * from ") TABLE, SQL_NTS);
if (!SQL_SUCCEEDED(rc)) {
return;
}
// 列情報
LV_COLUMN lvCol;
lvCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvCol.fmt = LVCFMT_LEFT;
lvCol.cx = 100;
rc = SQLNumResultCols(hstmt, &col);
g.vecci.reserve(col);
for (n = 0; n < col; n++) {
rc = SQLDescribeCol(hstmt, n+1, (SQLTCHAR *)buf, _countof(buf), NULL,
&datatype, NULL, NULL, NULL);
lvCol.pszText = buf;
lvCol.iSubItem = n;
ListView_InsertColumn(g.hList, n, &lvCol);
// 列情報
ColInfo ci;
ci.strName = buf;
ci.datatype = datatype;
g.vecci.push_back(ci);
// Text 12 SQL_VARCHAR
// Byte -6 SQL_TINYINT
}
// 行情報
LV_ITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
while (1) {
rc = SQLFetch(hstmt);
if (rc == SQL_NO_DATA) break;
if (rc == SQL_ERROR) break;
for (n = 0; n < col; n++) {
SQLGetData(hstmt, n+1, SQL_C_TCHAR, buf, _countof(buf), &len);
lvItem.pszText = buf;
lvItem.iSubItem = n;
if (n == 0) {
ListView_InsertItem(g.hList, &lvItem);
} else {
ListView_SetItem(g.hList, &lvItem);
}
}
lvItem.iItem++;
}
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}
//------------------------------------------------------------------------------
BOOL SaveTable(HWND hDlg)
{
TCHAR szPath[MAX_PATH];
TCHAR szBuf[256];
int nColNum = g.vecci.size();
// ファイルのオープン
_stprintf_s(szPath, _T("%s\\%s"), DATABASE, TABLE2);
FILE *pFile;
errno_t er = _tfopen_s(&pFile, szPath, _T("wt"));
if (er) {
MessageBox(hDlg, _T("ファイルのオープンに失敗しました。"), NULL, MB_OK);
return FALSE;
}
// ヘッダ行
_stprintf_s(szPath, _T("%s\\schema.ini"), DATABASE);
DWORD dw = GetPrivateProfileString(TABLE, _T("ColNameHeader"), NULL,
szBuf, _countof(szBuf), szPath);
if (_tcsicmp(szBuf, _T("true")) == 0) {
for (int nCol = 0; ; ) {
_ftprintf_s(pFile, _T("%s"), g.vecci[nCol].strName.c_str());
if (nColNum <= ++nCol) {
break;
}
_ftprintf_s(pFile, _T(","));
}
_ftprintf_s(pFile, _T("\n"));
}
// 書き込み
int nRowNum = ListView_GetItemCount(g.hList);
for (int nRow = 0; nRow < nRowNum; nRow++) {
for (int nCol = 0; ; ) {
ListView_GetItemText(g.hList, nRow, nCol, szBuf, _countof(szBuf));
switch (g.vecci[nCol].datatype) {
case SQL_VARCHAR:
_ftprintf_s(pFile, _T("\"%s\""), szBuf);
break;
case SQL_TINYINT:
_ftprintf_s(pFile, _T("%s"), szBuf);
break;
}
if (nColNum <= ++nCol) {
break;
}
_ftprintf_s(pFile, _T(","));
}
_ftprintf_s(pFile, _T("\n"));
}
fclose(pFile);
return TRUE;
}
// resource script
#include <windows.h>
#include "resource.h"
//------------------------------------------------------------------------------
IDD_MAIN DIALOGEX 100, 100, 320, 200
STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX
EXSTYLE WS_EX_APPWINDOW
CAPTION "CsvDirect"
FONT 9, "MS Pゴシック"
BEGIN
CONTROL "",IDC_LIST,"SysListView32",
WS_BORDER | WS_TABSTOP | LVS_REPORT,8,8,304,160
PUSHBUTTON "保存",IDC_SAVE,212,176,48,16
PUSHBUTTON "終了",IDCANCEL,264,176,48,16
END