前回までの話。
チェック行取得
いよいよこの開発最後の処理です。
まず一つ、前回作成物に一つ処理を追加します。
あのリストコントロール、チェックを入れるのが結構見づらかったので
グリッド線を入れることに。
Approval.cppのOnInitDialogに1行追加します。
BOOL CApproval::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: ここに初期化を追加してください
// リストコントロールの列作成
m_ctrlListApproval.SetExtendedStyle(m_ctrlListApproval.GetExtendedStyle() | LVS_EX_GRIDLINES);
// 略
}これでグリッド線が出来上がります。

続いて、承認or拒否にチェックが入っている行の取得です。
Idとチェック状態さえわかればテーブルを変更できます。
Approval.hに関数を追加します。
private:
void GetApprovalCondition(std::unordered_map<int, CString>* MapUpdate);その処理をApproval.cppで記述。
/**
* @fn
* @brief 承認・拒否状態取得
* @param std::unordered_map<int, CString>* Update対象行だけ取得
* @return なし
*/
void CApproval::GetApprovalCondition(std::unordered_map<int, CString>* MapUpdate)
{
int iRowCnt = m_ctrlListApproval.GetItemCount(); // 行数確認
for (int i = 0; i < iRowCnt; i++)
{
if (m_ctrlListApproval.GetItemText(i, 5) == _T("レ"))
{
// 承認列にチェックが入っている
(*MapUpdate)[_ttoi(m_ctrlListApproval.GetItemText(i, 0))] = _T("1");
}
else if (m_ctrlListApproval.GetItemText(i, 6) == _T("レ"))
{
// 拒否列にチェックが入っている
(*MapUpdate)[_ttoi(m_ctrlListApproval.GetItemText(i, 0))] = _T("2");
}
}
}承認列にチェックが入れば「1」を、拒否列にチェックが入れば「2」をマップに入れます。
なおチェックが入らなければマップに入れません。
この1や2も変数化が必要ですなぁ。
仕様が変わると大変だぜ(;´・ω・)
最後に、OKボタン(登録ボタン)が押下された際の処理を。
void CApproval::OnBnClickedOk()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
std::unordered_map<int, CString> MapUpdate;
GetApprovalCondition(&MapUpdate);
CMySQLManager UpdateRecord;
UpdateRecord.GetConnection();
if (UpdateRecord.bRecordTableChange(MapUpdate) == TRUE)
{
CDialogEx::OnOK();
}
}5行目まででマップに状態を格納します。
そして例のごとく、MySQL処理クラスに繋いで処理を呼応します。
いつものように、10行目はまだ未定義なので今はエラー出現。
この処理(Update文実行)が成功すれば、ダイアログは閉じます。
履歴テーブル更新
最後のSQL文かな?
MySQLManager.hに関数定義します。
public:
// 履歴テーブル更新
BOOL bRecordTableChange(std::unordered_map<int, CString> MapUpdate);今回、引数のマップは変更する必要はないので、
ポインタではなくマップ自体を入れます。
MySQLManager.cppで処理を書いていきます。
/**
* @fn
* @brief 履歴テーブル更新
* @param std::unordered_map<int, CString> MapUpdate
* @return なし
*/
BOOL CMySQLManager::bRecordTableChange(std::unordered_map<int, CString> MapUpdate)
{
try
{
m_con->setSchema(SCHEMA); //スキーマ選択
sql::SQLString strSqlQuery;
for (const auto& pair : MapUpdate)
{
CString strTemp;
strTemp.Format(_T("%d"), pair.first);
sql::SQLString strSqlId = strConverter(strTemp);
sql::SQLString strSqlApproval = strConverter(pair.second);
//Update文
strSqlQuery = "UPDATE " + TABLE_RECORD + " SET Approval = " + strSqlApproval + " WHERE Id = " + strSqlId;
// クエリを実行
std::unique_ptr<sql::PreparedStatement> pstmt(m_con->prepareStatement(strSqlQuery));
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
}
}
catch (sql::SQLException& e)
{
// 実行できなかった
ErrSQLException(e);
return FALSE;
}
return TRUE;
}やってることはいたって普通。
マップから履歴テーブルのIdとApproval状態を取り出し、
次々Updateを行います。
さて、これでビルドして処理を確認します。
動作確認
とりあえず、ユーザIdが11111の人を承認・拒否してみます。

登録を押すと処理が完了しました。
せめて、処理が完了したメッセージを出すべきですね。
忘れてました。
テーブルを見ますと、

ちゃんと11111の人のApproval列が変わっています。
一度ログアウトして、IDが11111の人でログインしてみます。

ちゃんと状態が反映されてるー( ;∀;)
順番は前の通りおかしいけど…
今思ったけど、これって辞書順なのかな?
ID21とか作ったら、2と3の間に入るとか?
まぁこれはいいです…。
ともかく、
これで作りたかった処理はすべて作り終えました。
感想
ブログ過去一大きな開発(って言っていいのか)を行いました。
一番難しかったのはマップを使う処理ですかね。
実は業務ではマップなんざ使ったことないので手探りで始めました。
しばらくはデータをクラス間で共有する時はマップにしようかな?
もっといいオブジェクトの作成があればそれにシフトするかも
仕様づくりも、まだまだでしたね。
自分で頑張って作ったつもりでも、
いざ処理を書き始めると足りない処理があったり、
こうした方がいいのでは?と(勝手に)変更したりと。
話が少し外れますが、今読んでる本、
SESはスキルアップの機会に恵まれないって書かれていて
理由を読んで「なるほどなぁ」と感心することも。
多分自分はこの先も、現場では基本設計以上に携わることはないと思います。
でも、そのままでいいかというとそうではなく、
ブログで少しずつ経験を積むことにしています。
ま、間違いを指摘してくれる人がいないので、
本当にそのやり方でいいのかの疑問はありますが。
話を戻すと。
作り終えて自分で気になったのは、
もう少し関数の共通化・もしくは細分化ができたらなぁ、と。
見返すと共通化できそうなか所ありますし、
逆に「そこは分けた方がいいだろ」ってのも。
後は、命名ですかね。
これも仕様がちゃんと定まっていれば迷うことはなかったかも。
いずれにせよ、次回の糧にしたいです。
終わりに
物品購入承認システムの作成を、一通り終えました。
ちょっと疲れました(;’∀’)
シリーズ自体は終了ですが、
1話だけ続編予定。
次のネタは、実は思いついているのですが、
少し休憩をはさんでまたブログにしようと考えてます。
(ま、システムではないんですが…)
それまでは小話が続きます。
今回はここまで。

コメント