VS2015 MFC对access2010数据库的增删改查
特点:1,把access内容导入list control后,可以实现双击修改list control的同时,修改数据库,也可以通过子弹窗修改数据库
2,查询可以通过combo—box实现便捷查询
3,删除可以通过单击listcontrol中的任意一行实现删除,如果单击到空白处,会提示
首先准备vs2015与access2010;
先连接数据库:网上方法有很多,我的office是64位的,所以debug,x64。!!!!!!否则连不上,如果你的机子上是32位的office,那就x86。
下面展示 连接数据库
的代码。
try {
CoInitialize(NULL);
m_pConnection = _ConnectionPtr(__uuidof(Connection));
m_pConnection->ConnectionTimeout = 5; //设置超时时间为5秒
m_pConnection->ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=access.accdb;";
m_pConnection->Open("", "", "", adConnectUnspecified);
/*_variant_t RecordsAffected;
CString strSql;
BSTR bstrSQL;
strSql = _T("CREATE TABLE acces(ID INTEGER,图书编码 REAL,图书名称 REAL,图书作者 REAL,出版社名 REAL )");//INTEGER
bstrSQL = strSql.AllocSysString();
m_pConnection->Execute(bstrSQL, &RecordsAffected, adCmdText);*/
AfxMessageBox(_T("数据库连接成功"));
}
catch (_com_error e) {
//m_pConnection->ConnectionTimeout = 5; //设置超时时间为5秒
AfxMessageBox(_T("数据库连接失败!"));
return FALSE;
}
一定要分清数据库和表,我这里在工程目录下放置数据库,我的数据库名字是access,数据库可以有很多表,我这次操作的表名是acces,(少一个s)。当然你可以任意名字。
下面展示 创建list control表头的代码
。
CoUninitialize();
// TODO: 在此添加额外的初始化代码
CRect rect;
// 获取编程语言列表视图控件的位置和大小
m_list.GetClientRect(rect);
// 为列表视图控件添加全行选中和栅格风格
m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
// 为列表视图控件添加三列
m_list.InsertColumn(0, _T("ID"), LVCFMT_CENTER, rect.Width() / 5, 0);
m_list.InsertColumn(1, _T("图书编码"), LVCFMT_CENTER, rect.Width() / 5, 0);
m_list.InsertColumn(2, _T("图书名称"), LVCFMT_CENTER, rect.Width() / 5, 1);
m_list.InsertColumn(3, _T("图书作者"), LVCFMT_CENTER, rect.Width() / 5, 2);
m_list.InsertColumn(4, _T("出版社名"), LVCFMT_CENTER, rect.Width() / 5, 3);
下面展示把access内容导入list control的代码
。
izengjia=1;//每次导入都置1,这个变量也是为了减少bug
m_list.DeleteAllItems();//清空列表
_variant_t RecordsAffected;
CString ha;
try {
ha = "select * from acces"; //查询ZRN表里的数据
m_pRecordset = m_pConnection->Execute(ha.AllocSysString(), &RecordsAffected, adCmdText); //获取记录集
int i = 0;
while (!m_pRecordset->adoEOF)
{
id = (char*)(_bstr_t)m_pRecordset->GetCollect("ID");
bm = (char*)(_bstr_t)m_pRecordset->GetCollect("图书编码"); //xm,dz,yb 分别为你自己数据库的列名
mc = (char*)(_bstr_t)m_pRecordset->GetCollect("图书名称"); //把这一记录中数据库里dz列下的值给字符串dz
zz = (char*)(_bstr_t)m_pRecordset->GetCollect("图书作者");
cb = (char*)(_bstr_t)m_pRecordset->GetCollect("出版社名");
m_list.InsertItem(i, _T(""));
m_list.SetItemText(i, 0, id); //添加到list Control 中的第i行的第一列下
m_list.SetItemText(i, 1, bm); //添加到list Control 中的第i行的第二列下
m_list.SetItemText(i, 2, mc); //添加到list Control 中的第i行的第三列下
m_list.SetItemText(i, 3, zz); //添加到list Control 中的第i行的第四列下
m_list.SetItemText(i, 4, cb); //添加到list Control 中的第i行的第五列下
i += 1; //下次循环指向第2行
m_pRecordset->MoveNext(); //移动到下一个记录
}
return;
}
catch (_com_error e)
{
CString a;
a.Format(_T("%s"), (LPCTSTR)e.Description());
//MessageBox(a);
return;
}
下面是增加数据,需要说明一下的就是,这里是对list control和access数据库同时操作,其实两者没什么关系,我是为了方便观察,才这样写;
下面展示 增加数据
。
这是增加数据的页面展示
try
{
CString strCmd;
GetDlgItemText(IDC_EDIT2, m_fu_bm);//对输入编辑框的内容进行获取
GetDlgItemText(IDC_EDIT3, m_fu_mc);
GetDlgItemText(IDC_EDIT5, m_fu_zz);
GetDlgItemText(IDC_EDIT6, m_fu_sm);
int nNowRow = m_list.GetItemCount();
CString str;
str.Format(_T("%d"), _ttoi(id) + izengjia);
int nRow = m_list.InsertItem(nNowRow, str);//插入的是某行的首列位置,返回的是该行的位置。
m_list.SetItemText(nRow, 1, m_fu_bm);//写入某行第二列内容信息
m_list.SetItemText(nRow, 2, m_fu_mc);//写入某行第二列内容信息
m_list.SetItemText(nRow, 3, m_fu_zz);//写入某行第二列内容信息
m_list.SetItemText(nRow, 4, m_fu_sm);//写入某行第二列内容信息
//strCmd="INSERT INTO [acces](ID,图书编码,图书名称,图书作者,出版社名) VALUES(10,'1003','传记','赵峰','人民')";//这里很容易把逗号写成中文的,在这里看不出来,要在sql中运行。
strCmd.Format(_T("INSERT INTO [acces](图书编码,图书名称,图书作者,出版社名) VALUES('%s','%s','%s','%s')"), m_fu_bm, m_fu_mc, m_fu_zz, m_fu_sm);
m_pConnection->Execute(strCmd.AllocSysString(), &RecordsAffected, adCmdText);
}
catch (_com_error &e)
{
CString a;
a.Format(_T("fail \r\n错误信息: %s"), (LPCTSTR)e.Description());//正确的提示错误
MessageBox(a);
return;
}
MessageBox(_T("添加成功!"),_T("消息"));
izengjia ++ ;//这是个全局变量,为了减少bug,如果调试成功了可以体会一下。
下面展示 修改数据
。
修改数据在父界面就一个按钮,我就不放在这里了,下面是修改数据的子界面。
这个是父页面修改按钮下的函数
_variant_t RecordsAffected;
POSITION ps = m_list.GetFirstSelectedItemPosition();
int nowRow = m_list.GetNextSelectedItem(ps);//选中的哪行的索引)
if (nowRow == -1) //nItem 没有选中列表数据时 返回值位-1
{
AfxMessageBox(_T("选中一行再更改"));
return;
}
int i = m_list.GetSelectionMark();
CString m;
m = m_list.GetItemText(i, 0);//第i行第0列
CString s;
int dm;
s = m_list.GetItemText(nowRow, 0);//第i行第0列
dm = _ttoi(s);
CString id = _T(""), bm = _T(""), mc = _T(""), zz = _T(""), sm = _T("");//初始化为空
id = m_list.GetItemText(nowRow, 0);
bm = m_list.GetItemText(nowRow, 1);
mc = m_list.GetItemText(nowRow, 2);
zz = m_list.GetItemText(nowRow, 3);
sm = m_list.GetItemText(nowRow, 4);
zibianjikuang_ok* dlg = new zibianjikuang_ok();//非模态对话框
dlg->m_zi_id = id;
dlg->m_zi_bm = bm;
dlg->m_zi_mc = mc;
dlg->m_zi_zz = zz;
dlg->m_zi_sm = sm;//传递到子编辑框过去了
dlg->Create(IDD_DIALOG1, this);
dlg->ShowWindow(SW_SHOW);
UpdateData(TRUE);
下面展示 子界面的代码
。主要是对确定按钮的修改,细节可以自行调通
CMFCaccessDlg * parent = (CMFCaccessDlg*)GetParent();
POSITION ps = parent->m_list.GetFirstSelectedItemPosition();
int nNowRow = parent->m_list.GetNextSelectedItem(ps);//选中的哪行的索引)
GetDlgItemText(IDC_EDIT1, zsm);//获取用户输入的内容
GetDlgItemText(IDC_EDIT2, zmc);
GetDlgItemText(IDC_EDIT3, zbm);//获取用户输入的内容
GetDlgItemText(IDC_EDIT4, zid);
GetDlgItemText(IDC_EDIT5, zzz);//获取用户输入的内容
parent->m_list.SetItemText(nNowRow, 0, zid);//插入的是某行的首列位置,返回的是该行的位置。
parent->m_list.SetItemText(nNowRow, 1, zbm);//写入某行第二列内容信息
parent->m_list.SetItemText(nNowRow, 2, zmc);//写入行第二列内容信息
parent->m_list.SetItemText(nNowRow, 3, zzz);//写入某行第二列内容信息
parent->m_list.SetItemText(nNowRow, 4, zsm);//写入某行第二列内容信息
CMFCaccessDlg *parent_dlg = (CMFCaccessDlg *)GetParent();// m_MFCaccessDlg; //强制转换为父窗口类型
parent_dlg->xiugaishujuku(); //调用父窗口函数,xiugaishujuku()是父cpp中的函数,在子窗口对其进行调用。
下面展示 CMFXCaccessDlg中xiugaishujuku()函数的代码
。
_variant_t RecordsAffected;
POSITION ps = m_list.GetFirstSelectedItemPosition();
int nowRow = m_list.GetNextSelectedItem(ps);//选中的哪行的索引)
if (nowRow == -1) //nItem 没有选中列表数据时 返回值位-1
{
AfxMessageBox(_T("选中一行再更改"));
return;
}
int i = m_list.GetSelectionMark();
CString s;
int dm;
s = m_list.GetItemText(nowRow, 0);//第i行第0列
dm = _ttoi(s);
try
{
CString strCmd;
CString n;
n = m_list.GetItemText(i, 1);//第i行第0列
CString x;
x = m_list.GetItemText(i, 2);//第i行第0列
CString y;
y = m_list.GetItemText(i, 3);//第i行第0列
CString z;
z = m_list.GetItemText(i, 4);//第i行第0列
strCmd.Format(_T("UPDATE acces SET [图书编码]='%s',[图书名称]='%s',[图书作者]='%s',[出版社名]='%s' WHERE [ID]=%d"), n, x, y, z,dm);
m_pConnection->Execute(strCmd.AllocSysString(), &RecordsAffected, adCmdText);
}
catch (_com_error &e)
{
MessageBox(e.Description(),_T("修改失败"), MB_ICONEXCLAMATION);
return;
}
MessageBox(_T("修改成功!"),_T("消息"));
下面展示 双击list control一行修改list control和数据库
。具体细节以后会更,或者下载我的工程
void CMFCaccessDlg::OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult)//双击的函数
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
POSITION ps = m_list.GetFirstSelectedItemPosition();
int nItem = m_list.GetNextSelectedItem(ps);//选中的哪行的索引)
if (nItem == -1) //nItem 没有选中列表数据时 返回值位-1
{
AfxMessageBox(_T("这里没有数据,不能执行修改操作"));
return;
}
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
CRect rc;
m_Row = pNMListView->iItem;//获得选中的行,全局变量
m_Col = pNMListView->iSubItem;//获得选中列,全局变量
if (m_Col == 0)
{
MessageBox(_T("ID不能修改"));
return;
}
int n = m_list.GetItemCount();//获取当前一共多少行
if (pNMListView->iSubItem != 0) //如果选择的是子项;
{
m_list.GetSubItemRect(m_Row, m_Col, LVIR_LABEL, rc);//获得子项的RECT;
m_edit_yincang.SetParent(&m_list);//转换坐标为列表框中的坐标
m_edit_yincang.MoveWindow(rc);//移动Edit到RECT坐在的位置;
m_edit_yincang.SetWindowText(m_list.GetItemText(m_Row, m_Col));//将该子项中的值放在Edit控件中;
m_edit_yincang.ShowWindow(SW_SHOW);//显示Edit控件;
m_edit_yincang.SetFocus();//设置Edit焦点,双击的数字变没
m_edit_yincang.ShowCaret();//显示光标,显示数字
m_edit_yincang.SetSel(-1);//将光标移动到最后
if (m_Row == n - 1)
{
m_list.InsertItem(m_Row + 1, _T(""));
}
}
*pResult = 0;
}
void CMFCaccessDlg::OnEnKillfocusEdit7()//这是修改的edit
{
// TODO: 在此添加控件通知处理程序代码
CString str;
m_edit_yincang.GetWindowTextW(str);//将指定窗口的标题拷贝到缓存区
m_list.SetItemText(m_Row, m_Col, str);//insertitem只操作第一列,set也是插入
_variant_t RecordsAffected;
CString s;
int dm;
s = m_list.GetItemText(m_Row, 0);//第i行第0列
dm = _ttoi(s);
if (m_Col == 1)
{
try
{
CString a;
a.Format(_T("update acces set [图书编码]='%s'where [ID]=%d "), str, dm);
m_pConnection->Execute(a.AllocSysString(), &RecordsAffected, adCmdText);
return;
}
catch (_com_error e)
{
CString a;
a.Format(_T("%s"), (LPCTSTR)e.Description());
MessageBox(a);
return;
}
}
if (m_Col == 2)
{
try
{
CString a;
a.Format(_T("update acces set [图书名称]='%s'where [ID]=%d "), str, dm);
m_pConnection->Execute(a.AllocSysString(), &RecordsAffected, adCmdText);
return;
}
catch (_com_error e)
{
CString a;
a.Format(_T("%s"), (LPCTSTR)e.Description());
MessageBox(a);
return;
}
}
if (m_Col == 3)
{
try
{
CString a;
a.Format(_T("update acces set [图书作者]='%s'where [ID]=%d "), str, dm);
m_pConnection->Execute(a.AllocSysString(), &RecordsAffected, adCmdText);
return;
}
catch (_com_error e)
{
CString a;
a.Format(_T("%s"), (LPCTSTR)e.Description());
MessageBox(a);
return;
}
}
if (m_Col == 4)
{
try
{
CString a;
a.Format(_T("update acces set [出版社名]='%s'where [ID]=%d "), str, dm);
m_pConnection->Execute(a.AllocSysString(), &RecordsAffected, adCmdText);
return;
}
catch (_com_error e)
{
CString a;
a.Format(_T("%s"), (LPCTSTR)e.Description());
MessageBox(a);
return;
}
}
m_edit_yincang.ShowWindow(SW_HIDE);
}
下面展示查询
。
这是查询的界面,关键字是当你在查询类别中选中了查询的一列后,数据的具体的查询内容
m_list.DeleteAllItems();//清空列表
UpdateData(TRUE);
try {
UpdateData(TRUE);
CString m_tablefield, m_searchsql;
UpdateData(TRUE);
GetDlgItemText(IDC_COMBO1, m_fu_ccombo);
m_tablefield = m_fu_ccombo;
GetDlgItemText(IDC_EDIT1, m_fu_id);
if (m_fu_ccombo == "ID")//如果是整数类型
{
try
{
m_tablefield = "ID";
int m;
m = _ttoi(m_fu_id);
m_searchsql.Format(_T("select* from acces where %s=%d"), m_tablefield, m);
m_pRecordset.CreateInstance("ADODB.Recordset");
m_pRecordset->Open(m_searchsql.GetBuffer(),
_variant_t((IDispatch*)m_pConnection, true),
adOpenStatic,
adLockOptimistic,
adCmdText);
//处理数据,并显示
_variant_t varbuffer;
long index = 0;//注意:必须是long类型
int countItem = 0;
CString str;
while (!m_pRecordset->adoEOF)
{
index = 0;
//读ID号
varbuffer = m_pRecordset->GetCollect(_variant_t(index));
if (varbuffer.vt != VT_NULL)
{
str.Format(_T("%d"), varbuffer.lVal);
m_list.InsertItem(countItem, str.GetBuffer());
}
//读其它的信息
while (index < 4)//显示出4列数据
{
index++;
varbuffer = m_pRecordset->GetCollect(_variant_t(index));
if (varbuffer.vt != VT_NULL)
{
str = (LPCTSTR)(_bstr_t)varbuffer;
m_list.SetItemText(countItem, index, str.GetBuffer());
}
}
m_pRecordset->MoveNext();
countItem++;
}
return;
}
catch (_com_error &e)
{
MessageBox(e.Description(), _T("数据库操作失败."), MB_ICONEXCLAMATION);
return;
}
}
m_searchsql.Format(_T("select* from acces where %s='%s'"), m_tablefield, m_fu_id);
m_pRecordset.CreateInstance("ADODB.Recordset");
m_pRecordset->Open(m_searchsql.GetBuffer(),
_variant_t((IDispatch*)m_pConnection, true),
adOpenStatic,
adLockOptimistic,
adCmdText);
//处理数据,并显示
_variant_t varbuffer;
long index = 0;//注意:必须是long类型
int countItem = 0;
CString str;
while (!m_pRecordset->adoEOF)
{
index = 0;
//读ID号
varbuffer = m_pRecordset->GetCollect(_variant_t(index));
if (varbuffer.vt != VT_NULL)
{
str.Format(_T("%d"), varbuffer.lVal);
m_list.InsertItem(countItem, str.GetBuffer());
}
while (index < 4)//显示出4列数据,可以根据实际情况修改
{
index++;
varbuffer = m_pRecordset->GetCollect(_variant_t(index));
if (varbuffer.vt != VT_NULL)
{
str = (LPCTSTR)(_bstr_t)varbuffer;
m_list.SetItemText(countItem, index, str.GetBuffer());
}
}
m_pRecordset->MoveNext();
countItem++;
}
}
catch (_com_error &e)
{
//AfxMessageBox(e.Description());
MessageBox(e.Description(), _T("数据库操作失败."), MB_ICONEXCLAMATION);
//if (m_pRecordset->State)
// m_pRecordset->Close();
return;
}
下面展示 combo box
。这个代码是在父cpp也就是CMFCaccessDlg的OnInitDialog()函数下写的。
而combo box不需要写。
m_fu_combo.AddString(_T("ID")); //添加字符串
m_fu_combo.AddString(_T("图书编码"));
m_fu_combo.AddString(_T("图书名称"));
m_fu_combo.AddString(_T("图书作者"));
m_fu_combo.AddString(_T("出版社名"));
m_fu_combo.SetCurSel(0); //默认选择第一个
下面展示 删除
。
删除在主界面就一个按钮,就不多说了。
int i = m_list.GetSelectionMark();
CString s;
s = m_list.GetItemText(i,0);//第i行第0列
CString strCmd;
try
{
CString strCmd;
int m;
m = _ttoi(s);
strCmd.Format(_T("delete *from acces where ID=%d"),m);
m_pConnection->Execute(strCmd.AllocSysString(), &RecordsAffected, adCmdText);//execute,执行
}
catch (_com_error &e)
{
CString a;
a.Format(_T("fail \r\n错误信息: %s"), (LPCTSTR)e.Description());//正确的提示错误
MessageBox(a);
return;
}
MessageBox(_T("删除成功!"),_T("完成"));
POSITION ps = m_list.GetFirstSelectedItemPosition();
int nItem = m_list.GetNextSelectedItem(ps);//选中的哪行的索引)
if (nItem == -1) //nItem 没有选中列表数据时 返回值位-1
{
AfxMessageBox(_T("这里没有数据,不能执行删除操作"));
return;
}
m_list.DeleteItem(nItem);
UnlockWindowUpdate();//点完删除就刷新
如果你对里面的变量看不懂,可以下载。也可以问我,我看见会回复。