上一篇主要讨论了,InfoPath如何利用VSTA来把表单数据按行写入数据库,这个数据库,作者为了方便,以列表库代替。列表库的使用反而给开发带来了随意定制视图的方便功能。很多人都在想如何InfoPath与SQL结合,笔者却做了一个与列表的结合。因为列表库有现成的WebSerivce可以使用,数据库可能就需要自己编程WebService。
上一篇主要讨论了解决方案,下面主要把代码呈现给大家:
接上篇: 要点4: 如何在InfoPath的VSTA下编写代码,
上一篇摘要:http://www.cnblogs.com/dosboy/archive/2007/11/30/977535.html
上一篇主要内容:
讨论了InfoPath如何利用VSTA来把表单数据按行写入数据库,这个数据库作者为了方便,以列表库代替。
接上篇: 要点4: 如何在InfoPath的VSTA下编写代码,
"工具"->"提交选项"->"使用代码自定义操作"->"编辑代码",
在提交选项中插入以下自定义提交代码:
public void FormEvents_Submit(object sender, SubmitEventArgs e)

{
this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:ErrInfo", this.NamespaceManager).SetValue("");
FormSave();

if (this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:SaveError", this.NamespaceManager).Value == "true")

{
e.CancelableArgs.Message = "提交过程有失败,请查看错误信息";
e.CancelableArgs.Cancel = true;
}

else

{
e.CancelableArgs.Cancel = false;
}
}
代码中使用了一个方法,FormSave(),这是一个自定的方法,其作用就是:
1 把表单提交进入表单库,
如果是新建表单,使用不允许覆盖的提交方式.
如果是更新以前的表单,使用可以覆盖的提交方式.
2 把表单的记录更新进入列表库,
代码通过遍历表单中重复表的每一行数据,如果该行数据在"列表"中可以找到,即有相同的单号\名称\规格,那就采用Update方法,如果找不到,那就采用新建New.
然后代码继续遍历"列表"中入库单号等于该入库单的项,如果列表中的项,新提交的表单中没有,说明使用者在使用InfoPath的时候把它删除了,那么就从"列表"中删除它!
3 错误处理,
private void FormSave()

{
// 在此处编写代码。

string strResult = "";
this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:SaveError", this.NamespaceManager).SetValue("false");

try

{

//进行表单的保存操作,如果保存没有办法进行,就不进行记录的更新

if (this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:isNew", this.NamespaceManager).Value == "true")

{ //如果是新建表单,不允许覆盖库中的记录

((FileSubmitConnection)this.DataConnections["新建提交"]).Execute();

this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:isNew", this.NamespaceManager).SetValue("false");
}
else
//如果不是新建表单,而是更新以前的表就,使用可以覆盖的提交
((FileSubmitConnection)this.DataConnections["主提交"]).Execute();

strResult += "入库单保存成功!\r\n";

//读取列表的记录
SPSite site = new SPSite("http://f2003-server/");
SPList list = site.OpenWeb("/project").Lists["物资出入库记录"];

//初始化WebService
物资入库.myws.Lists listService = new 物资入库.myws.Lists(); //获得Lists对象

listService.Credentials = System.Net.CredentialCache.DefaultCredentials; //设置验证票

listService.Url = "http://f2003-server/project/_vti_bin/Lists.asmx"; //非常重要,指定了下面所有的操作都是针对project这个子网站



//遍历重复表group1中的每一项
XPathNavigator NodeIter = this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:group1", this.NamespaceManager);

//定义操作字串
string strBatch = "";

foreach (XPathNavigator myf in NodeIter.SelectChildren(XPathNodeType.Element))

{
//对于重复表中的每一行,到列表去查找,如果找到就使用Update,找不到就使用New

SPQuery myQ = new SPQuery();

string QueryText = "<Where><And><And><Eq><FieldRef Name='" + list.Fields["入库单编号"].InternalName + "'/><Value Type='Text'>"
+ MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:入库单编号", this.NamespaceManager).Value
+ "</Value></Eq><Eq><FieldRef Name='" + list.Fields["物资名称"].InternalName + "'/><Value Type='Text'>"
+ myf.SelectSingleNode("my:物资名称", NamespaceManager).Value + "</Value></Eq></And>"
+ "<Eq><FieldRef Name='" + list.Fields["规格型号"].InternalName + "'/><Value Type='Text'>"
+ myf.SelectSingleNode("my:规格型号", NamespaceManager).Value + "</Value></Eq>"
+ "</And></Where>";

myQ.Query = QueryText;

SPListItemCollection items = list.GetItems(myQ);

if (items.Count == 0)

{
//如果没有找到就新增

strBatch += "<Method ID='" + myf.SelectSingleNode("my:序号", NamespaceManager).Value + "' Cmd='New'><Field Name='ID'>New</Field>";

}

else

{
//如果找到了就更新

strBatch += "<Method ID='" + myf.SelectSingleNode("my:序号", NamespaceManager).Value + "' Cmd='Update'><Field Name='ID'>" + items[0].ID.ToString() + "</Field>";
}

//扁历所有列表的字段,如果与表单的字段名称相同,就更新该字段
foreach (SPField field in list.Fields)

{
//重复表内的字段
foreach (XPathNavigator myfield in myf.SelectChildren(XPathNodeType.Element))

//比较相同
if (field.Title == myfield.Name.Substring(myfield.Name.IndexOf(":") + 1))

{
strBatch += "<Field Name='" + field.InternalName + "'>" + myfield.Value + "</Field>";
}


//重复表外的,单号、收货人、日期等等字段
foreach (XPathNavigator myfield in this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields", this.NamespaceManager).SelectChildren(XPathNodeType.Element))

if (field.Title == myfield.Name.Substring(myfield.Name.IndexOf(":") + 1))

{
strBatch += "<Field Name='" + field.InternalName + "'>" + myfield.Value + "</Field>";
}




}

strBatch += "</Method>";
}


//下面检查,此次表单编辑,是否删除了记录
SPQuery myQ2 = new SPQuery();



string QueryText2 = "<Where><Eq><FieldRef Name='" + list.Fields["入库单编号"].InternalName + "'/><Value Type='Text'>"
+ MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:入库单编号", this.NamespaceManager).Value
+ "</Value></Eq></Where>";

myQ2.Query = QueryText2;

int MethodId = NodeIter.SelectChildren(XPathNodeType.Element).Count + 1;

SPListItemCollection allItems = list.GetItems(myQ2);
foreach (SPListItem item in allItems)

{
bool stillExist = false; //原来记录中的项,在新的表单中还存在?

foreach (XPathNavigator myf in NodeIter.SelectChildren(XPathNodeType.Element))

{
if (item["物资名称"].ToString() == myf.SelectSingleNode("my:物资名称", this.NamespaceManager).Value)

{
//物资名称相同,规格型号都为空
if (item["规格型号"] == null && (myf.SelectSingleNode("my:规格型号", this.NamespaceManager).Value == null || myf.SelectSingleNode("my:规格型号", this.NamespaceManager).Value == ""))
stillExist = true;
else

{
if (item["规格型号"] != null)
if (item["规格型号"].ToString() == myf.SelectSingleNode("my:规格型号", this.NamespaceManager).Value)
stillExist = true;
}

}
}

if (!stillExist)

{//如果老项已经在新的编辑过程中删除了,那么就执行删除Method
strBatch += "<Method ID='" + MethodId.ToString() + "' Cmd='Delete'><Field Name='ID'>" + item.ID.ToString() + "</Field></Method>";
}



}



XmlDocument xmlDoc = new System.Xml.XmlDocument();

System.Xml.XmlElement elBatch = xmlDoc.CreateElement("Batch");

elBatch.SetAttribute("OnError", "Continue");


elBatch.InnerXml = strBatch;


XmlNode ndReturn = listService.UpdateListItems("676CFD44-76D0-4161-966D-DA1B55CB6CD3", elBatch);



foreach (XmlNode ndResult in ndReturn.ChildNodes)

{


if (Convert.ToInt32(ndResult.FirstChild.Value) == 0)

strResult += "序号:" + ndResult.Attributes["ID"].Value.ToString().Replace("New", "新建").Replace("Update", "更新").Replace("Delete", "删除") + "成功!";
else

{
strResult += "序号:" + ndResult.Attributes["ID"].Value.ToString().Replace("New", "新建").Replace("Update", "更新").Replace("Delete", "删除") + "失败!(代码" + Convert.ToInt32(ndResult.FirstChild.Value) + ")";
this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:SaveError", this.NamespaceManager).SetValue("true");
}


}




this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:ErrInfo", this.NamespaceManager).SetValue(strResult);
}
catch (Exception ex)

{
this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:SaveError", this.NamespaceManager).SetValue("true");
this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:ErrInfo", this.NamespaceManager).SetValue(ex.Message);
}

}
在表单的启动事件,用来设置IsNew变量的状态。
public void FormEvents_Loading(object sender, LoadingEventArgs e)

{
// 在此处编写代码。

if(!this.New)
this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:isNew", this.NamespaceManager).SetValue("false");
else
this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:isNew", this.NamespaceManager).SetValue("true");
}
代码事项:使用了三个表单字段来进行状态维护,IsNew,SaveError,ErrInfo,
1 isNew,用来判断这个表单操作,是不是新建.平时当然可以使用表单的this.New来判断,但是由于是没有使用"保存",而使用了了提交到表单库的操作,你提交进去表单库后,this.New不会变成False.
2 SaveError,判断整个操作是否成功,如果有一个记录没有成功更新,也为True;
3 ErrInfo,如果失败,就显示失败信息,这个在表单中有一个文本框与之帮定.
要点5:事件处理程序:处理删除表单表单操作
表单内部中的更新(插入、删除、更新)都可以反应在“列表”中,那么使用者如果删除表单文件呢?
大家可以自己思考哦。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库