Showing posts with label InfoPath 2007. Show all posts
Showing posts with label InfoPath 2007. Show all posts

Friday, October 18, 2013

SharePoint 2013: Migrating InfoPath 2007 Form Text Display Issue

Scenario: You open an InfoPath 2007 form in InfoPath Designer 2013. You publish it to SharePoint 2013.

Problem:  When rendering the form in SharePoint 2013, the text and/or background colors do not display correctly:

 
 

Resolution:

1. Open the form in InfoPath Designer 2013.

2. Select some text on the form and click on the Normal font format. (It may already be selected but click it anyway).

 
 
3. You will be prompted to update the template. Click Yes:
 


4. Save the form changes and re-publish the form to SharePoint 2013.

Form rendering is now corrected:

 

Thursday, November 8, 2012

InfoPath 2007/2010/2013: Dynamically Populate a Nested Repeating Table from a Secondary Data Source

This post builds on top of my original population of repeating table post. I had a reader ask about a nested solution in which the repeating group not only contained fields, but yet another repeating group.

The scenario of the form fields looks like the following:


In my examples (on my blog and in my InfoPath How-To book), I used Regions and Offices as data sources (they are SharePoint lists but web services or other data sources work the same way - just different XPath). Offices has a lookup column for the Region.

For the nested scenario, I decided to create a third datasource named Clients. The Clients have a relationship to Offices. Therefore, in my Clients SharePoint list, I have a lookup column to Offices. The overall relationships are:
  • Regions can have one-to-many Offices (An Office can only have one Region)
  • Offices can have one-to-many Clients (A Client can only belong to one Office)

My Clients data source contains the Client Name (Title), Address, and Phone along with the Office field which is the Office ID:


So now, when I select a Region from the drop-down in my form, I want to get the Offices for that Region along with all of the Clients that belong to that Office. Since it's a nested structure it calls for a nested loop within the Populating code-behind (see my previous post for context):

(click on image to zoom in)


The nested loop code involves these steps:
  • Creating the data source object for the Clients list
  • Setting the query value to the current Office ID
  • Executing the query against the data source
  • Looping through the data source results and populating the nested repeating table structure
The results speak for themselves:


 I will have more details on these steps as well as downloadable code in my upcoming InfoPath with SharePoint 2013 How-To book! Stay tuned!

 

Friday, February 4, 2011

InfoPath 2007/2010: Tracking Changes in InfoPath

One of the coolest solutions in my InfoPath How-To book is the tracking of changes within a form. Although this requires code-behind the results are well worth the effort. Although my latest solution is for InfoPath 2010, you can use the same code and concepts in InfoPath 2007. My original solution was indeed in InfoPath 2007.

While writing the solution for the book, I realized I did not have the latest code and that there were some missing steps that I coded at the client site to handle line breaks. Have no fear! I am now working for that previous customer and reviewed the code that I was missing.

On Page 280 of my book, there is Listing 18.5. You'll see the "Get the Changes" line which calls the Diff method of the SPDiffUtility. Before this line, enter the following:

oldValue = oldValue.Replace("\n", SPDiffUtility.ChangeOpenTag + "<br></br>" + SPDiffUtility.ChangeCloseTag);
newValue = newValue.Replace("\n", SPDiffUtility.ChangeOpenTag + "<br></br>" + SPDiffUtility.ChangeCloseTag);


You'll need to declare oldValue and newValue prior to these lines. You can set these to the event values e.OldValue and e.NewValue. Without using these replace statements, any line breaks in the original text do not get reflected in the track changes text. Replacing the line breaks (\n) with the html shown above preserves the new lines in the tracked changes.


If you found this useful, please help support my SharePoint and .NET user group (Philly SNUG) by clicking on the logo below.

Saturday, September 25, 2010

InfoPath 2010: The Infamous Form Name

Yes the infamous form name issue. I rant on about this in my InfoPath Book. I always had an out with the dilemma of new versus updates and keeping the same name.



Several members of my audience at SharePoint Saturday Baltimore eluded to a good solution and one of my colleagues came up with the same idea. It's not anything new but a good altenative if the fields you decide to use can be edited and changed.


The first part of this requires a common theme in form template design; determining if the form is a new instance. I have used a IsNew-type field in the past where the default is 0 or false and when the form instance is rendered (or submitted), rules force it to 1 or true.


So for the form name, instead of using a function at the time of submission, use a field value that has been pre-calculated. If the form is new, create the form name and store that into a field. Then, use that field as the form name that is saved during submission.



This way, the form name will never change during edits. So using an entered field, todays date, etc. in the form name will never have the chance to change since the form name is initially figuired out when the form is new.



Monday, September 13, 2010

InfoPath 2007/2010/2013: Populate a Repeating Table from a Secondary Data Source

Psst! I have a new nested solution posted here.

Background
In attempting to create a solution within form code to satisfy the scenerio/requirements below, I found several different posts/links that described certain functions. Each link only provided a piece of the puzzle. This post puts all the pieces together.


Scenario/Requirements
Clicking a button or changing a selection in an InfoPath form needs to query a web service (or any secondary data source) based on that selection and populate a repeating table with the data. If the selection changes, the repeating table entries need to be cleared and re-populated with the new set of data.


Assumptions
The querying of the secondary data source (such as a web service) based on selections is already in place (this can be easily done with rules). We just need the proper form code within the control change-event to handle the repeating table population.



Solution Piece-by-Piece

Namespace Variable
Within the changed event form code (using Visual Studio for Office Applications) the first thing we need is the standard namespace variable so we can use that throughout:

string myNamespace = NamespaceManager.LookupNamespace("my");

Access Web Service-Based Secondary Data Source
There is a MainDataSource object at the form level but how can you access secondary data sources? If the datasource is named "GetData" here is the code to access and setup the XPath objects for looping:

DataSource ds = DataSources["GetData"];
XPathNavigator domNav = ds.CreateNavigator();
XPathNodeIterator rows = domNav.Select("/dfs:myFields/dfs:dataFields/tns:GetDataResponse/tns:GetData/NewDataSet/DynamicData", NamespaceManager);

Looping Through the Secondary Data Source
You can loop through the XPathNodeIterator collection using a while-loop. The source fields data can be retrieved by using the Current pointer within the XPathNodeIterator:

while (rows.MoveNext())
{
string accountID = rows.Current.SelectSingleNode("AccountID",NamespaceManager).Value.ToString();
string accountNumber = rows.Current.SelectSingleNode("AccountNumber",NamespaceManager).Value.ToString();
string amount = rows.Current.SelectSingleNode("Amount",
NamespaceManager).Value.ToString
}

Populating the Repeating Table
The repeating table is actually part of the main data source so we can access that and use the XMLWriter to write the field values from the web service to the table. The code below will live within the loop from above:

using (XmlWriter writer = MainDataSource.CreateNavigator().SelectSingleNode("/my:MainDataSource/my:group1", NamespaceManager).AppendChild())
{


writer.WriteStartElement("group2", myNamespace);
writer.WriteElementString("Amount",myNamespace ,amount);
writer.WriteElementString("AccountID", myNamespace, accountID);

writer.WriteElementString("AccountNumber", myNamespace,
accountNumber);

writer.WriteEndElement();
writer.Close();
}

The above assumes the repeating table created a Group1\Group2 data source entry. You must look at the main datasource to determine the group names.

ALSO! VERY IMPORTANT! The order in which you write the values to the table should be the order that they appear in the main data source. So if you expand the group1 and group2 and see field1, field2, field3, that is the order you must have in the code above. Otherwise you will receive a non-datatype schema validation error.


Clearing Previous Entries
Before anything happens, we need to check if there are already rows in the repeating table and remove them. This must be done by removing the rows in a descending fashion because the count actually represents the highest index.

First we check to see if there are any rows in the repeating table and if so we loop through and delete them. Notice how the actual row is accessed using the SelectSingleNode (SelectSingleNode("/my:MainDataSource/my:group1/my:group2[row#]):

XPathNavigator rTable = MainDataSource.CreateNavigator();
XPathNodeIterator tableRows = rTable.Select("/my:MainDataSource/my:group1/my:group2", NamespaceManager);
if (tableRows.Count > 0)
{


for (int i = tableRows.Count;i > 0; i--)
{
XPathNavigator reTable =
MainDataSource.CreateNavigator();

XPathNavigator reTableRows =
reTable.SelectSingleNode("/my:MainDataSource/my:group1/my:group2[" + i + "]", NamespaceManager);

reTableRows.DeleteSelf();
}
}




Solution - Complete Code
//Get namespace
string myNamespace = NamespaceManager.LookupNamespace("my");
//Clear any previous entries
XPathNavigator rTable = MainDataSource.CreateNavigator(); XPathNodeIterator tableRows = rTable.Select("/my:MainDataSource/my:group1/my:group2", NamespaceManager);

if (tableRows.Count > 0)
{
for (int i = tableRows.Count;i > 0; i--)
{
XPathNavigator reTable =
MainDataSource.CreateNavigator();
XPathNavigator reTableRows =
reTable.SelectSingleNode("/my:MainDataSource/my:group1/my:group2[" + i + "]",
NamespaceManager);

reTableRows.DeleteSelf();
}
}
//Connect to secondary data source
DataSource ds = DataSources["GetData"];
XPathNavigator domNav = ds.CreateNavigator(); XPathNodeIterator rows = domNav.Select("/dfs:myFields/dfs:dataFields/tns:GetDataResponse/tns:GetData/NewDataSet/DynamicData", NamespaceManager);

//Loop through secondary data source and populate the repeating table

while (rows.MoveNext())
{

string accountID =
rows.Current.SelectSingleNode("AccountID", NamespaceManager).Value.ToString();

string accountNumber =
rows.Current.SelectSingleNode("AccountNumber",NamespaceManager).Value.ToString();

string amount =
rows.Current.SelectSingleNode("Amount", NamespaceManager).Value.ToString();

using (XmlWriter writer =
MainDataSource.CreateNavigator().SelectSingleNode("/my:MainDataSource/my:group1",
NamespaceManager).AppendChild())


{
writer.WriteStartElement("group2", myNamespace);
writer.WriteElementString("Amount",myNamespace ,amount);
writer.WriteElementString("AccountID",
myNamespace, accountID);

writer.WriteElementString("AccountNumber", myNamespace,
accountNumber);

writer.WriteEndElement();
writer.Close(); }

}


WHAT ABOUT A NESTED REPEATING TABLE? THE ANSWER IS HERE!

You can download a sample form and project code with the purchase of my bestselling InfoPath book:



The Nested Solution will be part of my new InfoPath with SharePoint 2013 book download.
 

Matched Content