MFCで、CSVからデータを抽出・表示させる処理 7

前回までの記事

ヘッダー部表示制御

前回、条件変更処理で、どの列を表示させるかをチェックボックスのチェック状態で決めていました。

その後、ゲッター関数でTestResultDlgの方にも状態が保存されていることも確認しました。

今回はこれを使ってヘッダー部の制御を行います。

まず初めに、ヘッダー部に表示させる教科を配列化します。

TestResultDlg.hに定義。

private:
	CString m_strSubject[SUB_NUM];		// 教科名

次いで、TestResultDlg.cppのコンストラクタに初期化処理を。
ついでに、昔作ったメンバ変数m_iCSVNum(CSVの行数)について、
「初期化しろや」と怒られていたのを放置していたので、
ここで0で初期化しておきます。

CTestResultDlg::CTestResultDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_TESTRESULT_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_iCSVNum = 0;
	m_strSubject[SUB_JA] = _T("国語");
	m_strSubject[SUB_MA] = _T("数学");
	m_strSubject[SUB_EN] = _T("英語");
	m_strSubject[SUB_SC] = _T("理科");
	m_strSubject[SUB_SS] = _T("社会");

}

最後に、ヘッダー部の表示をさせる関数DispHeadについて、
修正を行います。
表示非表示の状態はメンバ配列m_bCheckTRDlgで確認できます。

void CTestResultDlg::DispHead()
{
	CString strHead = strAlighnment(_T("ID"), CENT_AL, 6);
	for (int iLoop = SUB_JA; iLoop < SUB_NUM; iLoop++)
	{
		if (m_bCheckTRDlg[iLoop])
		{
			//条件変更チェックボックスの状態がチェックあり
			strHead += strAlighnment(m_strSubject[iLoop], CENT_AL, 6);
		}
	}

	SetDlgItemText(IDC_EDIT_DISP_HEADER, strHead);	// 表示
}

ただこれだけだと、DispHead関数は呼ばれないので、
条件変更ボタンで「保存&表示」が押されたタイミングで呼ぶことにします。
ついでに、どうせデータも再表示させる処理をつくるので、DispData関数も呼応しておきます。

void CTestResultDlg::OnBnClickedButtonConditional()
{
	// 略
	if (iRTN == IDOK)
	{
		// 「保存&表示」ボタン
		for (int iLoop = SUB_JA; iLoop < SUB_NUM; iLoop++)
		{
			//略
		}

		DispHead();	//ヘッダー再表示
		DispData();	//データ再表示
	}
	else
	{
		// キャンセルボタン
	}
}

一回ビルドします。

条件変更でこのように、国語と理科のチェックを外します。

「保存&表示」ボタンを押すと

ヘッダー部は国語と理科が消えてくれました。

データ部表示制御

今度はデータ部表示制御です。

やることは列の表示選択と、点数による制御。

まずは列表示制御から。

以下、DataDisp関数の修正箇所。

void CTestResultDlg::DispData()
{
	// 略

	for (int iLoop = 0; iLoop < m_iCSVNum; iLoop++)
	{
		// 略

		for (int iSub = SUB_JA; iSub < SUB_NUM; iSub++)
		{
			if (m_bCheckTRDlg[iSub])	//この条件を新規追加
			{
				strData += strAlighnment(strConvertHanZen(values[iSub]), RIGHT_AL, 6);	//各データを全角に直して右詰
			}
		}
		
		// 略
	}

	SetDlgItemText(IDC_EDIT_DISP_DATA, strData);	// 表示
}

再度ビルドします。

このデータに対し、先ほど同様国語と理科のチェックボックスを外すと。

確かに非表示になってくれてます。

最後、点数の条件です。
例えば上記の例だと、数学を0点以上97点以下にした場合、
IDが1の学生は数学が98点なので、ID=1の行は表示させないようにします。

考えとしては、strData +=を行う前に、まずその行を表示させるかさせないか判断しなければいけません。
表示させない場合、外側のfor文へ回すことに。

void CTestResultDlg::DispData()
{
	CString strData = _T("");
	std::vector<CString> values;
	int iID = 0;
	CString strID = _T("");

	for (int iLoop = 0; iLoop < m_iCSVNum; iLoop++)
	{
		iID = iLoop + 1;				// ID
		strID.Format(_T("%d"), iID);	// ID CStringで
		values = GetTableData(strID);	// IDに対するデータ

		//行表示チェック
		for (int iSub = SUB_JA; iSub < SUB_NUM; iSub++)
		{
			if (m_bCheckTRDlg[iSub])
			{
				//表示させる場合、点数チェック
				int iScore = _ttoi(values[iSub]);	//点数
				int iIJO = _ttoi(m_strIJOTRDlg[iSub]);	//点以上
				int iIKA = _ttoi(m_strIKATRDlg[iSub]);	//点以上
				if (iScore < iIJO || iIKA < iScore)
				{
					// 条件変更で設定した値を満たしていないので、行を表示させない
					goto OuterLoopContinue;
				}
			}
		}

		 //問題なければ表示処理
		strData += strAlighnment(strConvertHanZen(strID), RIGHT_AL, 6);		// IDは全角に直して右詰

		for (int iSub = SUB_JA; iSub < SUB_NUM; iSub++)
		{
			if (m_bCheckTRDlg[iSub])
			{
				strData += strAlighnment(strConvertHanZen(values[iSub]), RIGHT_AL, 6);	//各データを全角に直して右詰
			}
		}
		
		if (iLoop != m_iCSVNum - 1)
			strData += _T("\r\n");	//最終行以外は改行

		OuterLoopContinue:
			continue;
	}

	SetDlgItemText(IDC_EDIT_DISP_DATA, strData);	// 表示
}

さぁ、これでビルドします。

条件はこの通り。

国語が30~90の間の生徒を表示させます。
後ろに見えますが、10番までですと表示は1、5、7、8、9が該当するはずです。
さて、いかに。

よっしゃい!
╭( ・ㅂ・)و

早いけど感想

とりあえずこの時点で、一番やりたかったことはできました。

いや、ここまで作ったの久々だから少しだけ感動しています。

後やりたいリストは

  • CSVのフォーマットチェック
  • 明らかに使ってない箇所の削除
    (ボタン全然使ってないところがありますね…)
  • (追加)条件付き表示時の合計算出
  • その他あったら便利そうな処理追加

です。

後2、3回で終わるかな?

今回ソース修正箇所は上に記載した個所で事足るので、
成果物表示は割愛します。

MFCで、CSVからデータを抽出・表示させる処理 8
前回までの記事余談早速余談なのですが。超今更ですが、情報セキュリティマネジメント試験を先日受けまして、まぁまぁギリギリでしたが合格していました。ちゃんとした結果が公表されたら、何か記事に書こうかと思います。多分、受けようと思ったきっかけや、...

コメント

タイトルとURLをコピーしました