Initially I wanted to use a rule-only approach but it ended up being too cumbersome; I had to resort to code :(
I will use a time card with date range as an example here. The repeating table will have one row for each day within the date range I have selected.
Structure of my repeating table:
Here is the code that does all the magic. I have created it as an event triggered when a view is switched.
Function to append a child node:
public void AddDetailField(XmlDocument doc, XmlNode group, string fieldName, string fieldValue)
{
XmlNode field = doc.CreateElement(fieldName, NamespaceManager.LookupNamespace("my"));
XmlNode node = group.AppendChild(field);
node.InnerText = fieldValue;
}
Function to populate the repeating rows in infopath form. Take note that the first child node needs to be removed.
public void AutoPopulateTimeSheet(XPathNavigator nav)
{
string start = nav.SelectSingleNode("/my:myFields/my:Data/my:StartDate", this.NamespaceManager).Value;
string end = nav.SelectSingleNode("/my:myFields/my:Data/my:EndDate", this.NamespaceManager).Value;
DateTime dtStart = Convert.ToDateTime(start);
DateTime dtEnd = Convert.ToDateTime(end);
// Delete first row
XPathNavigator itemNav = nav.SelectSingleNode(
"/my:myFields/my:Details/my:Detail[1]", NamespaceManager);
// Delete the row
if (itemNav != null)
itemNav.DeleteSelf();
foreach (DateTime day in EachDay(dtStart, dtEnd))
{
// Create group
XmlDocument doc = new XmlDocument();
XmlNode group = doc.CreateElement("Detail", NamespaceManager.LookupNamespace("my"));
// Add fields
string dayOfWeek = GetDay(day);
AddDetailField(doc, group, "Date", day.ToString("yyyy-MM-dd"));
AddDetailField(doc, group, "Day", dayOfWeek);
if (regular.ToLower().Equals("true") && !(dayOfWeek.Equals("Sat") || dayOfWeek.Equals("Sun")))
{
AddDetailField(doc, group, "Regular", "8");
}
else
{
AddDetailField(doc, group, "Regular", "0");
}
AddDetailField(doc, group, "Makeup", "0");
AddDetailField(doc, group, "DoubleTime", "0");
AddDetailField(doc, group, "OverTime", "0");
AddDetailField(doc, group, "Vacation", "0");
AddDetailField(doc, group, "PTO", "0");
AddDetailField(doc, group, "Holiday", "0");
AddDetailField(doc, group, "Bereavement", "0");
AddDetailField(doc, group, "Jury", "0");
AddDetailField(doc, group, "TimeWOPay", "0");
AddDetailField(doc, group, "WorkComp", "0");
AddDetailField(doc, group, "ServiceAward", "0");
AddDetailField(doc, group, "Total", "0");
doc.AppendChild(group);
nav.SelectSingleNode(
"/my:myFields/my:Details",
NamespaceManager).AppendChild(doc.DocumentElement.CreateNavigator());
}
}
Lastly, the view switched event:
public void FormEvents_ViewSwitched(object sender, ViewSwitchedEventArgs e)
{
XPathNavigator nav = this.MainDataSource.CreateNavigator();
string company = nav.SelectSingleNode("/my:myFields/my:Controls/my:Company", this.NamespaceManager).Value;
// if workflow has not kicked off and filled this hidden value, means user is submitting for the first time
if (string.IsNullOrEmpty(company) && this.CurrentView.ViewInfo.Name.Equals("Details"))
{
AutoPopulateTimeSheet(nav);
}
}
Note: Including code-behind in InfoPath will elevate them to administrator approved forms. You can't publish them directly to a Form library. You will need to upload the form using Central Administration.
No comments:
Post a Comment