前回までの話。
リストコントロール表示処理作成
今回はメイン画面のリストコントロール内に、
自分の申請状況を表示させる処理を作ります。
まず初めに、マップの作製。
ユーザ情報表示のやり方だとどうもうまくいかず、
グループや項目の表示方法はうまくいったので、
今回はマップを採用します。
作り方は項目マップと同じです。
構造体定義
SupplyRequestManager.hに、以前KoumokuValueなる構造体を定義しました。
今回はその履歴版です。
struct RecordValue
{
CString strGroupName; // グループ名称
CString strKoumokuName; // 項目名称
CString strPrice; // 項目値段
CString strApproval; // 承認状態
};リストコントロール内に表示させる内容です。
マップ定義
SupplyRequestManagerDlg.hに、メンバマップを定義します。
また、リスト表示させる準備も。
private:
std::unordered_map<int, RecordValue> m_MapRecord; // 履歴テーブル格納
CListCtrl m_ctrlListRecord; // リストコントロール
void ShowRecordMap(); //申請履歴表示関数
public:
std::unordered_map<int, RecordValue>* GetMapRecord() { return &m_MapRecord; }取得処理
項目マップと同じく、OnInitDialogに取得処理を書きます。
BOOL CSupplyRequestManagerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 略
CMySQLManager GroupKoumokuGetter;
GroupKoumokuGetter.GetConnection(); //接続確立
GroupKoumokuGetter.SetGroupMap(GetMapGroup()); // グループテーブルデータをマップに格納
GroupKoumokuGetter.SetKoumokuMap(GetMapKoumoku()); // 項目テーブルデータをマップに格納
GroupKoumokuGetter.SetRecordMap(GetMapRecord()); // 履歴テーブルデータをマップに格納
// 列設定
m_ctrlListRecord.InsertColumn(0, _T("ID"), LVCFMT_LEFT, 100);
m_ctrlListRecord.InsertColumn(0, _T("グループ"), LVCFMT_LEFT, 200);
m_ctrlListRecord.InsertColumn(0, _T("項目"), LVCFMT_LEFT, 200);
m_ctrlListRecord.InsertColumn(0, _T("値段"), LVCFMT_LEFT, 100);
m_ctrlListRecord.InsertColumn(0, _T("承認状態"), LVCFMT_LEFT, 100);
ShowRecordMap(); // リスト再表示
UpdateData(FALSE);
return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
}12行目以降を追加しました。
例によってSetRecordMapはまだ定義していないので現段階ではエラーが出ます。
GroupKoumokuGetterはGroupKoumokuRecordGetterとかに変更した方がいいかもしれませんね。
そこはお好みで。
そして、先ほど定義したメンバ変数m_ctrlListRecordとリストコントロールを紐づけます。
void CSupplyRequestManagerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST_MAIN, m_ctrlListRecord);
}表示処理
履歴テーブルから取得してマップに格納したデータを表示させます。
こちらも、項目を表示させたのと同じ手法で。
/**
* @fn
* @brief リスト再表示処理
* @param なし
* @return なし
*/
void CSupplyRequestManagerDlg::ShowRecordMap()
{
// すべてのアイテム(行)を削除
m_ctrlListRecord.DeleteAllItems();
int iRow = 0; // 行番号
LVITEM lvItem{};
lvItem.mask = LVIF_TEXT;
for (const auto& pair : m_MapRecord)
{
// ID列
lvItem.iSubItem = 0;
CString strTemp;
strTemp.Format(_T("%d"), pair.first);
lvItem.pszText = strTemp.GetBuffer();
m_ctrlListRecord.InsertItem(&lvItem);
// グループ名称列
lvItem.iSubItem = 1;
strTemp = pair.second.strGroupName;
lvItem.pszText = strTemp.GetBuffer();
m_ctrlListRecord.SetItem(&lvItem);
// 項目名称列
lvItem.iSubItem = 2;
strTemp = pair.second.strKoumokuName;
lvItem.pszText = strTemp.GetBuffer();
m_ctrlListRecord.SetItem(&lvItem);
// 値段列
lvItem.iSubItem = 3;
strTemp = pair.second.strPrice;
lvItem.pszText = strTemp.GetBuffer();
m_ctrlListRecord.SetItem(&lvItem);
// 承認状態列
lvItem.iSubItem = 4;
strTemp = pair.second.strApproval;
lvItem.pszText = strTemp.GetBuffer();
m_ctrlListRecord.SetItem(&lvItem);
iRow++;
}
}1列目に申請Id、2列目に申請したグループ名称、
3列目に申請した項目名称、4列目に申請した値段、
5列目に承認状態を表示させます。
これで表示はOK。
SQL文作成
recordテーブルからデータを取得し、マップに格納させます。
MySQLManager.hに関数定義。
public:
// 申請履歴マップセット
void SetRecordMap(std::unordered_map<int, RecordValue>* MapRecord);MySQLManager.cppで具体的に処理を書いていきます。
/**
* @fn
* @brief 申請履歴テーブルセット
* @param std::unordered_map<int, RecordValue>* マップポインタ
* @return なし
*/
void CMySQLManager::SetRecordMap(std::unordered_map<int, RecordValue>* MapRecord)
{
try
{
m_con->setSchema(SCHEMA);
CSupplyRequestManagerApp* pApp = static_cast<CSupplyRequestManagerApp*>(AfxGetApp());
CString strUserId = pApp->strGetUserId(); // ユーザID取得
sql::SQLString strsqlUserID = strConverter(strUserId); // ユーザID型変換
sql::SQLString strSQL = "SELECT " + TABLE_RECORD + ".Id AS RecordID, "; // recordテーブルのID
strSQL += TABLE_GROUP + ".Name AS GroupName, "; // groupテーブルのグループ名称
strSQL += TABLE_KOUMOKU + ".Name AS KoumokuName, "; // koumokuテーブルの項目名称
strSQL += TABLE_KOUMOKU + ".Price AS KoumokuPrice, "; // koumokuテーブルの項目値段
strSQL += TABLE_RECORD + ".Approval AS RecordApproval "; // recordテーブルの承認状態
strSQL += "FROM " + TABLE_RECORD;
strSQL += " JOIN " + TABLE_KOUMOKU + " ON " + TABLE_RECORD + ".KoumokuId = " + TABLE_KOUMOKU + ".Id";
strSQL += " JOIN " + TABLE_GROUP + " ON " + TABLE_KOUMOKU + ".GroupId = " + TABLE_GROUP + ".Id";
strSQL += " WHERE " + TABLE_RECORD + ".UserId = " + strsqlUserID; // recordテーブルでユーザIDが現ユーザ
// クエリを実行
std::unique_ptr<sql::PreparedStatement> pstmt(m_con->prepareStatement(strSQL));
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
// 結果を処理
if (res->next())
{
do
{
int iRecordId = 0;
CString strGroupName = _T("");
CString strKoumokuName = _T("");
CString strKoumokuPrice = _T("");
int iApproval = 0;
CString strApproval = _T("");
std::string strsqlCol = res->getString("RecordID"); // ID列の取得
CString strCol = strConvertFromUTF8ToUTF16(strsqlCol); // 型変換
iRecordId = _ttoi(strCol);
strsqlCol = res->getString("GroupName"); // グループ名称列の取得
strCol = strConvertFromUTF8ToUTF16(strsqlCol); // 型変換
strGroupName = strCol;
strsqlCol = res->getString("KoumokuName"); // 項目グループID列の取得
strCol = strConvertFromUTF8ToUTF16(strsqlCol); // 型変換
strKoumokuName = strCol;
strsqlCol = res->getString("KoumokuPrice"); // 値段列の取得
strCol = strConvertFromUTF8ToUTF16(strsqlCol); // 型変換
strKoumokuPrice = strCol;
strsqlCol = res->getString("RecordApproval"); // 承認状態の取得
strCol = strConvertFromUTF8ToUTF16(strsqlCol); // 型変換
iApproval = _ttoi(strCol);
if ((ApprovalMode)iApproval == enPending)
{
strApproval = _T("申請中");
}
else if ((ApprovalMode)iApproval == enApprovaled)
{
strApproval = _T("承認済");
}
else if ((ApprovalMode)iApproval == enRejected)
{
strApproval = _T("拒否");
}
else
{
CString strMes = _T("");
strMes.Format(_T("データに問題があります。管理者へ連絡を!\r\nrecord ID:%d"), iRecordId);
AfxMessageBox(strMes);
return;
}
(*MapRecord)[iRecordId] = { strGroupName, strKoumokuName, strKoumokuPrice, strApproval };
} while (res->next());
}
else
{
// 該当データが何もないけどそれは問題ない
}
}
catch (sql::SQLException& e)
{
// 実行できなかった
ErrSQLException(e);
return;
}
}やってることは、グループマップや項目マップ作成と変わりありません。
テーブルからデータ取得して、マップに入れてるだけです。
強いて言えば、SQLが少しだけ複雑になってますね。
SQL久しぶりに書いたせいでちょっと手こずったのは内緒…。
変数を使わないとこうなります。
SELECT
record.Id AS RecordID,
'group'.Name AS GroupName,
koumoku.Name AS KoumokuName,
koumoku.price AS KoumokuPrice,
record.Approval AS RecordApproval
FROM
record
JOIN
koumoku ON record.KoumokuId = koumoku.Id
JOIN
'group' ON koumoku.GroupId = 'group'.Id
WHERE
record.UserId = ●●● // 現ユーザ以上で、メイン画面のリストコントロールに表示させる処理ができたはず。
動作確認
今回、ユーザを複数人作ってみました。

ソートがうまくできてないですが、今回の作成範囲外なので…。
IDが11111、22222、33333でログインし、それぞれ申請を行ってみます。
色々申請を行い、テーブルはこんな感じに。

11111が4回、22222が2回、33333が3回申請しています。
さて、それぞれでログインすると…。



微妙にID順になってないー(;´∀`)
でも取りたい内容はちゃんと取得できていました。
項目IDから、ちゃんとグループ名称も取れてます。
ちょっと感動。
CListCtrlでソーする関数があるようですが、
今回は力尽きたので諦めます。
終わりに
今回はメイン画面の申請状況を取得する処理を作りました。
ようやく終わりが見えてきた…。
誰だよこんな画面数多い機能作ろうとしたやつ
何回か書いてますが、課題はリストコントロールのソートですかね。
そこはまた機会があれば調べてみます。
今回はここまで。

コメント