The Microsoft Office InfoPath 2003 Software Development Kit (SDK) contains sample forms, tools, macros, code libraries, and documentation to assist with InfoPath form development in both InfoPath 2003 and InfoPath 2003 SP1.
Here’s what’s new in the updated SDK
Download the SDK today! Go to http://www.microsoft.com/office/infopath and look in the Downloads section at the bottom of the page.
InfoPath supports a feature called Conditional Formatting which allows among other things to show or hide sections of the form based on some condition.
However, the underlying XML data still stays there even though it is not visible in the view. What if one wants to remove the XML data altogether? It is easy to achieve this by writing a little bit of code.
First of all, a trick: an optional leaf field can be wrapped in an Optional Section without adding any additional nodes in the Data Source. Suppose that your data source looks like that:
myFields
field1
Instead of dragging field1 into the view (which will produce a Text Box, assuming its datatype is a string), right-click on it, select More… and pick Optional Section with Controls.
Now the Text Box is wrapped in an Optional Section and you can remove or insert it as desired.
At this time, suppose that you want field1 appear conditionally based on a state of a Check Box bound to some node (let’s call it field2). Attach an “OnAfterChange” event to it with the following code:
function msoxd_my_field2::OnAfterChange(eventObj)
{
if (eventObj.IsUndoRedo || eventObj.Operation != "Insert")
return;
}
if (eventObj.NewValue == "true")
XDocument.View.ExecuteAction("xOptional::insert", "field1_1");
else
XDocument.View.SelectNodes(XDocument.DOM.selectSingleNode("/my:myFields/my:field1"));
XDocument.View.ExecuteAction("xOptional::remove", "field1_1");
Here, we use the xOptional::insert command to insert field1 (and hence the Optional Section) when the Check Box is checked, and xOptional::remove to remove it when the Check Box is unchecked.
A few comments on the code above:
P.S. The conditional presence technique is especially useful in scenarios where the schema contains optional elements that are not allowed to be blank (which could be a desirable design in some scenarios where the XML-consuming backend cannot handle xsi:nils).
P.P.S. The technique of calling View.SelectNodes() can solve the ExecuteAction() focus/context problem. The ExecuteAction() documentation states that sometimes calling ExecuteAction() from button’s onClick can fail. Calling View.SelectNodes() from onClick shold remedy to this problem.
Although InfoPath doesn't have a Change Tracking feature built-in like Word and some of the other Office System applications, read on for guidance on how to implement it in your own solutions.
There are several problems to decide before jumping into implementation: where do you want to store change tracking information, how do you map between list of changes and elements, tracking information protection, and what format you use to store change tracking information.
Storage options
Depending on schema of XML there are several options:
Format options
1. XML friendly.
If you want your tracking information to be processed using some form of normal XML handling (XSL, XML readers, XPath navigation) then you should use XML sub-trees to store change tracking information.For example: <changes> <change forElement="element1233" date="2004-06-12" author="john" type="textChange">New text</change> <change forElement="element1233" date="2004-06-14" author="fred" type="textChange">Don't writen new text!</change> </changes>
If you want your tracking information to be processed using some form of normal XML handling (XSL, XML readers, XPath navigation) then you should use XML sub-trees to store change tracking information.
For example:
<changes> <change forElement="element1233" date="2004-06-12" author="john" type="textChange">New text</change> <change forElement="element1233" date="2004-06-14" author="fred" type="textChange">Don't writen new text!</change> </changes>
2. Custom text format
If you can't use normal XML for some reasons (i.e. storage options 1.b, 2.a) then you can develop text format to store the data. You can use approach close to XML (i.e. just store sub-tree as string) or even go with Base64 encoded binary.
Mapping between element and tracking information
1. Direct access.
If you can put tracing information right into element you are interested in then you don't need any mapping. Note that this approach requires you to think through deletion scenario because the element itself might be deleted along with it's tracking information.
If you can put tracing information right into element you are interested in then you don't need any mapping.
Note that this approach requires you to think through deletion scenario because the element itself might be deleted along with it's tracking information.
2. Element ID.
This is an easy option to implement if you have or can establish persistent unique element identifiers for each element you want to track changes. It could be attribute on elements or some combination of attributes and values of element.Note that you can not use XPath to element as unique id if you have any repeating content you want to track changes on.The problem here is that you need to have good ID and should think through insertion of elements.
This is an easy option to implement if you have or can establish persistent unique element identifiers for each element you want to track changes. It could be attribute on elements or some combination of attributes and values of element.
Note that you can not use XPath to element as unique id if you have any repeating content you want to track changes on.
The problem here is that you need to have good ID and should think through insertion of elements.
3. Position based mapping.
This is the most complex option to implement. If you can't have any identifiers for element you had to go with position based mapping. I.e. <change forElement="/root/items[0]/item[4]/component[3]" date="2004-06-12" author="john" type="textChange">New text</change>where forElement contains the XPath to the element of interest.The main problem here is that you have to dynamically update all mappings on element insertions through the tree.
This is the most complex option to implement. If you can't have any identifiers for element you had to go with position based mapping. I.e.
<change forElement="/root/items[0]/item[4]/component[3]" date="2004-06-12" author="john" type="textChange">New text</change>
where forElement contains the XPath to the element of interest.
The main problem here is that you have to dynamically update all mappings on element insertions through the tree.
Change tracking information protection
You should consider if and how you want to protect this data. Approaches would vary from digitally signing each change (or editing session) to "who cares if it is changed?"
Coding ideas for simplest case
You have unique element IDs that somehow get generated for elements. You are interested in recording changes in text value of an element.
Here is sample of XML you want to record changes for:
<root> <items> <item id = "12"><textToTrack>text</textToTrack></item> <item id = "23"><textToTrack>text</textToTrack></item> <item id = "55"><textToTrack>text</textToTrack></item> </items></root>
The approach choosen to store the data: separate from the data as subtree of the <root> node, and no protection and tamper detection for tracking information.
Here is example of XML with tracking information.
<root> <changes> <change forElement="12" date="2004-06-12" author="john" type="textChange" ><old>text</old><new>Shining new text</new></change> <change forElement="12" date="2004-06-14" author="fred" type="textChange" ><old>Shining new text</old><new>Don't write new text!</new></change> <change forElement="23" date="2004-06-14" author="fred" type="delete"></change> </changes> <items> <item id="12"><textToTrack>Don't write new text!</textToTrack></item> <item id="55"><textToTrack>text</textToTrack></item> </items></root>
To code this in InfoPath you need:
Make sure schema allows <changes> to be inserted. I.e. In designer for new solution create this structure in the Data Source task pane.
Figure out how to get user name if needed.
Add an "OnAfterChange" listener for <items> node, and implement the following pseudo-code:
IF change = "add" AND node-name = "item" make sure ID is generated for "add" record (ID, added) information. IF change = "remove" AND node-name = "item" record (ID, deleted) IF (change = "add OR change = "remove" OR change = "change") AND node-name = "textToTrack" record (ID, textChange, oldValue, newValue)
Where ID is "id" attribute of corresponding "item" node, and record means append all needed information a <changes> collection. Record function should also take care of merging change information for the same date/user like if node was added in this session all changes should be combined into "added" record, rather then creating multiple "changed" sections.
Note that "undo" user actions will rollback change as well as tracking information. If you store data in separate file you should take care of undo yourself.
When it comes to InfoPath, will you squeak by with a passing grade or graduate at the very top of your class? Take a short quiz on Office Online and find out exactly where you stand.
http://office.microsoft.com/assistance/quiz.aspx?AssetID=QZ010971581033
If that was too simple, here's the next question for you InfoPath whizzes out there: What questions would you ask to find out if someone knows InfoPath inside and out?
Andrew Ma, a tester on the InfoPath team, has created a Visual Basic 6.0 version of the InfoPath Hands-On Lab for creating custom controls. You can find it here on Andrew's blog:
http://blogs.msdn.com/ajma/articles/213868.aspx
The option to “Submit as Email” doesn’t include the form in the body of the mail, so here’s another way to encourage your form-fillers to send their forms as email and include that body.
This script could be used in a Blogger form to turn on the Mail Envelope when the user switches to the “Email” view. That event could be triggered by the form-filler using the View menu, or even by a Rule on a button. It also makes some decisions based on the user’s current role so you can see how to do that.
function XDocument::OnSwitchView(eventObj) {
var mail = XDocument.View.Window.MailEnvelope;
if (XDocument.View.Name == "Email") {
// get nodes from DOM
var blog = XDocument.DOM.selectSingleNode("/dfs:myFields/dfs:dataFields/d:blog");
var id = blog.selectSingleNode("@ID");
var title = blog.selectSingleNode("@Title");
var blogger = blog.selectSingleNode("@BloggerName");
var replies = blog.selectNodes("d:reply/@ReplyName");
// Set To field to include blog and the original blogger
mail.To = "blog; " + blogger.text;
// Set CC field to include all the replies (minus the current one)
if (replies != null) {
var cc = "";
for (var i = 0; i < replies.length - 1; i++) {
cc += replies(i).text + "; ";
mail.CC = cc;
// Set subject to look like a thread
var subject = "Blog " + id.text + " - " + title.text;
if (XDocument.Role != "Create")
subject = "RE: " + subject;
mail.Subject = subject;
// Show the mail envelope
mail.Visible = true;
else {
mail.Visible = false;
We're getting reports from some users who are having problems installing the InfoPath SDK. The problem appears to be caused by intermittent network traffic issues causing downloads to fail part-way through. You'll end up with a file that appeared to download but is missing some or most of the data. Restarting the download sometimes accesses the incomplete cached version, which doesn't improve the situation.
The file size of InfoPathSDK.msi downloaded from http://www.microsoft.com/downloads/details.aspx?FamilyId=351F0616-93AA-4FE8-9238-D702F1BFBAB4&displaylang=en should be 4.34 MB (4,552,192 bytes). If you end up with a smaller file it's been truncated due to network problems, and the install will fail. Clear your browser cache (in IE: Tools | Internet Options, Delete Files...) and try the download again.