MS Office Forum / General MS InfoPath Questions / March 2008
Render InfoPath 2007 Rich Text in Word 2007 and Retain Formatting
|
|
Thread rating:  |
jogannon - 05 Mar 2008 02:54 GMT Thanks to a S.Y.M Wong-A-Ton 'recipe,' a weekly status report form is accurately converting string and date types through use of XSLT and C# when the Word .docx version of this report (differently formatted with company logo, etc.) is opened. However, data entered in the form's rich text controls understandably lose their formatting (e.g., end of paragraph/line breaks, lists, font display characteristics). The question is how to modify the .xsl file or use an alternative approach for transformation. With the former, I tried integrating xml code from a technique described by Stephane Bouillon for the 2003 versions of each app, but that probably failed due to 2003 vs 2007 compatibility issues. Stephane suggested looking at Brian Jones' explanation of Content Controls. I explored that for awhile and it led to the Open XML 'alternative format chunks' specification. This seems like a fascinating and powerful method, but I am looking for the IP --> Word integration aspect, whiooich is not addressed in the content I have thus far discovered.
Does anyone have any suggestions for moving me along the path to resolution of this issue, or better yet, some applicable example(s)?
Thanks for your consideration,
Joe
 Signature Joe
S.Y.M. Wong-A-Ton - 05 Mar 2008 06:26 GMT Hi Joe,
Have you already tried posting this question in the Word newsgroup? People might have more ideas there...
I'm not a Word expert, but I think your options are limited here. :) I also read about the afChunk element. It seems like a viable solution. However, I've not tried it out.
What you could do is extract the XHTML of the rich text field of an InfoPath form and then manually try to embed it in a DOCX file using the afChunk element just as an isolated test. If that works, you can keep your existing transformation using the XSL method and then after the transformation use the System.IO.Packaging objects to create a relationship and add the XHTML for the rich text to the package.
Other than that, I do not have any suggestions, but it's worth a try. Let us know if it works; I'm sure there are many more people out there wanting to do the same... --- S.Y.M. Wong-A-Ton
> Thanks to a S.Y.M Wong-A-Ton 'recipe,' a weekly status report form is > accurately converting string and date types through use of XSLT and C# when [quoted text clipped - 18 lines] > > Joe jogannon - 06 Mar 2008 02:24 GMT Hi S.Y.M Wong-A-Ton, Well, I went that route and have had a response from one of the Word Dev Team. It appears more and more that the InfoPath-Word interaction may have rich text dropping in the crack between the two. I am continuing to explore the approaches involving afchunk, content controls and a way to handle XHTML within XML. Will let you know if I 'luck out' in the process. As always, thanks for your interst and advice.
Joe
 Signature Joe
> Hi Joe, > [quoted text clipped - 41 lines] > > > > Joe jogannon - 07 Mar 2008 02:32 GMT Hi again, My major 'mental block' is less on the packaging of the parts, including additions to Content_Types.xml, document.xml.rels, etc., or even how to supplement the current C# code behind the InfoPath form's "Convert to Word" button in order to handle this. Rather, it is with the actual creation of the .rtf (or is it .xhtml?) file, which contains the XHTML-formatted, aFChunk data (e.g., a <ul> bullet list) that will be added to that package. Even some example to illustrate the way to select the form's RTF control(s) from other controls in the data source, and to properly stream/write the data to the .rtf file, would be helpful at this stage.
Any further guidance, concerning these issues, will certainly help me navigate this new territory and it will be most appreciated.
Thanks for your consideration.
 Signature Joe
> Hi Joe, > [quoted text clipped - 41 lines] > > > > Joe S.Y.M. Wong-A-Ton - 07 Mar 2008 03:10 GMT Before you dive into code, did you manually try adding the contents of an XHTML file to a DOCX? If that does not work, then it does not make sense to try to do it via code. :)
To retrieve the XHTML of an RTF field in InfoPath, you need to use SelectSingleNode() to retrieve the node for the RTF field and then use InnerXml instead of Value to retrieve the XHTML contents of that field. You can then use normal System.IO classes to write that XHTML data to either a Stream or a file. The contents of an RTF field in InfoPath is XHTML. This is HTML that conforms to a standard, so to save this to a file, the file would become a .htm or .html file and *not* a .rtf file. --- S.Y.M. Wong-A-Ton
> Hi again, > My major 'mental block' is less on the packaging of the parts, including [quoted text clipped - 57 lines] > > > > > > Joe jogannon - 07 Mar 2008 03:37 GMT Your reply is particularly rapid, timely and enlightening. After a great deal of research and reading, I just went through all of the steps laid out in http://openxmldeveloper.org/forums/Thread/2744.aspx (Most relevantly, what follows) These are the steps to attach RTF content to WordProcessingML document.
1. Create a rtf file (test.rtf) and place along with [Content_Types].xml file or in a folder
2. Add an entry into [Content_Types].xml as
<Default Extension="rtf" ContentType="application/rtf" />
3. In the document.xml.rels file (in _rels folder), add an entry for relationship to this file as.... (I will end it here)
Low and behold, .rtf does NOT work. I have been struggling all day to know which to apply, and you clarified that immediately. Sorry if I misinterpreted your otherwise clear instructions. I have already saved it as a .htm file and will (manually) package accordingly. One question concerns the exact method for extracting the XHTML data in an RTF control. What I just did was to extract the entire OuterXML reference:
<my:upFront> - <ul xmlns="http://www.w3.org/1999/xhtml" style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px" type="disc"> <li>some things</li> <li>more things</li> </ul> </my:upFront>
paste this to Word 2007 and save it as a .htm file. Should I include all of the above, such as the namespace?
Thanks again. You are making my day, late as it is (c. 10:30P EST).
 Signature Joe
> Before you dive into code, did you manually try adding the contents of an > XHTML file to a DOCX? If that does not work, then it does not make sense to [quoted text clipped - 71 lines] > > > > > > > > Joe S.Y.M. Wong-A-Ton - 07 Mar 2008 04:01 GMT You only need what's inside of my:upFront. But to include this in an HTML file that is valid, I think you will have to add additional HTML tags like BODY etc. I'm not sure what the exact specs are for XHTML, but you should be able to find them on www.w3.org. First try it without any extra tags, and if that does not work, you'll have to make the HTML file XHTML valid. --- S.Y.M. Wong-A-Ton
> Your reply is particularly rapid, timely and enlightening. After a great > deal of research and reading, I just went through all of the steps laid out [quoted text clipped - 107 lines] > > > > > > > > > > Joe jogannon - 07 Mar 2008 04:10 GMT Understood. I just stripped the <my:upFront> tags and it rendered this in the holding place within the Word .docx:
<ul xmlns="http://www.w3.org/1999/xhtml" style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px" type="disc"> <li>some things</li> <li>more things</li> </ul>
For me, this is progress. I will go looking for the other XHTML tags, according to the spec.
Thanks so much.
 Signature Joe
> You only need what's inside of my:upFront. But to include this in an HTML > file that is valid, I think you will have to add additional HTML tags like [quoted text clipped - 115 lines] > > > > > > > > > > > > Joe S.Y.M. Wong-A-Ton - 07 Mar 2008 04:26 GMT No worries.
Hey Joe, if it is working as is, you do not need to go look up the specs for XHTML. I think if you call the file .txt and reference it in the DOCX but tell the DOCX that it is HTML, it should work. This is perfect, since you do not have to add any additional tags for the XHTML data from InfoPath to work. You can just use the contents of the RTF field as is.
If you have to store it in a file, I'd suggest just putting the RTF contents in a file and trying it out like that without adding the extra tags. If that does not work, then dig into the XHTML. --- S.Y.M. Wong-A-Ton
> Understood. I just stripped the <my:upFront> tags and it rendered this in > the holding place within the Word .docx: [quoted text clipped - 129 lines] > > > > > > > > > > > > > > Joe jogannon - 07 Mar 2008 05:25 GMT Bingo!
• some things • more things
What was finally rendered. Here are some lessons learned.
1) Save as a .txt file with UTF-8 encoding, not as .htm nor as .rtf
2) The entry in the [Content_Types].xml should then read, correspondingly: <Default Extension="txt" ContentType="application/xhtml+xml" /> (Note: application/xhtml and application/html fail to display anything)
3) The document.xml.rels file reads: <Relationship Id="rId11" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/upFront.txt" TargetMode="Internal" />
4) I placed the altChunk tags between the next abutting </w:p><w:p> tags after my <w:t>Up Front</w:t> header, and that reads: <w:altChunk r:id="rId11"> <w:altChunkPr w:val="off" /> </w:altChunk>
So, 'manually,' it is doable. Tomorrow, I will tackle the C# code behind to get it automated.
Hopefully, this repays a bit for your time and the insight I received.
Thanks, as always, for your considerable help and encouragement.
 Signature Joe
> No worries. > [quoted text clipped - 143 lines] > > > > > > > > > > > > > > > > Joe jogannon - 07 Mar 2008 08:33 GMT Forgot the important 5th point, the fact that the <html></html>tags are necessary for proper rendering (without inner tags being exposed) of formatted text. In this case:
<html> <ul xmlns="http://www.w3.org/1999/xhtml" style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px" type="disc"> <li>some things</li> <li>more things</li> </ul> </html>
That's it. I will test for other formatting later, after producing effective C# code behind the 'Convert' button. Your advice made this a less daunting task.
 Signature Joe
> No worries. > [quoted text clipped - 143 lines] > > > > > > > > > > > > > > > > Joe S.Y.M. Wong-A-Ton - 07 Mar 2008 22:54 GMT Thanks for sharing your findings. I'm sure they'll help others who are trying to do the same. --- S.Y.M. Wong-A-Ton
> Forgot the important 5th point, the fact that the <html></html>tags are > necessary for proper rendering (without inner tags being exposed) of [quoted text clipped - 159 lines] > > > > > > > > > > > > > > > > > > Joe jogannon - 09 Mar 2008 10:14 GMT I am very close to automating this, but the following code causes the relationship to be added to /_rels/.rels.xml and NOT to the mandatory /word/_rels/document.xml.rels:
// add the aFChunk relationship Uri relativeAltUri = PackUriHelper.GetRelativeUri(uri, uri1); packWordPrint.CreateRelationship(relativeAltUri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/" + "2006/relationships/aFChunk", "rId11");
where uri is the Uri for /word/document.xml and uri1 is the Uri for the RTF's .txt file output. This output is successfully written to the /upFront.txt part and the [Content_Types].xml includes the line:
<Default Extension="txt" ContentType="application/xhtml+xml" />
It is noteworthy that I can manually copy the relationship specification to /word/_rels/document.xml.rels in the package and the Word .docx opens as ti should, with the bulleted text in the proper location.
If you can help me to get over this 'bit of a hump,' I believe we have the solution in hand.
Thanks much,
 Signature Joe
> Thanks for sharing your findings. I'm sure they'll help others who are trying > to do the same. [quoted text clipped - 164 lines] > > > > > > > > > > > > > > > > > > > > Joe jogannon - 09 Mar 2008 17:43 GMT Found the culprit and understand the logic--I think. The problem is that I referenced the Package ('packWordPrint' in your original code) relationship for defining the aFChunk to the target part (RTF to text object), instead of the proper PackagePart ('documentPart' in your original code) relationship. The former places the <Relationship> entry(ies) into /_rels/.rels.xml. The latter places them correctly into the document.xml.rels under /word/_rels. If you want, I will document this whole approach to send your way. Then, you can choose to optimize the code behind the form's Convert button and publish the 'recipe' on your site as an extension of the 'Convert InfoPath to Word 2007' article.
BTW, I already have a second RTF control working in this solution; and the final two will be from RTF controls embedded within repeating sections.
I cannot thank you enough for all of your help and encouragement.
 Signature Joe
> Thanks for sharing your findings. I'm sure they'll help others who are trying > to do the same. [quoted text clipped - 164 lines] > > > > > > > > > > > > > > > > > > > > Joe S.Y.M. Wong-A-Ton - 10 Mar 2008 01:22 GMT Glad you finally got it solved! And well done!
And yes, please! I'd like for you to send your documentation my way (either via my blog on you know which page or via the "Send Feedback" option on this page http://aspalliance.com/author.aspx?uId=58992 , which should accept XML tags and code. You can also just post the code here in this newsgroup, if you like. When I get a chance, I'll either update the article or write a new one and give you credit for doing the research and coming up with the solution.
The repeating section sounds like yet another challenge, so I hope you get it to work.
Thanks once again for reporting your challenges, findings, and solutions here; they will be helpful to the InfoPath community in general. --- S.Y.M. Wong-A-Ton
> Found the culprit and understand the logic--I think. The problem is that I > referenced the Package ('packWordPrint' in your original code) relationship [quoted text clipped - 180 lines] > > > > > > > > > > > > > > > > > > > > > > Joe jogannon - 11 Mar 2008 04:12 GMT You're welcome. Please give me some time to work around the next set of hurdles--loops on the C# code behind the button side and recursive techniques with the XML in the .xsl file. Then, I will send upload the solution particulars, as you recommended, with the Send Feedback option.
 Signature Joe
> Glad you finally got it solved! And well done! > [quoted text clipped - 197 lines] > > > > > > > > > > > > > > > > > > > > > > > > Joe jogannon - 11 Mar 2008 08:42 GMT I have encountered another bump in the road when I try to concatenate the value of a counter to a label within a While loop (C#). Worse yet, incrementing a Uri. So, for example, I have this less than elegant code to handle one of the RTF controls embedded within a repeating section. It is interesting that the OuterXml listing shows the expected sample XHTML output in Debug mode. First, I will list the code for a non-repeating RTF control that WORKS:
XPathNavigator domNav = MainDataSource.CreateNavigator(); XPathNodeIterator rows = domNav.Select( "/my:myFields/my:salesActivities/my:salesActivity", NamespaceManager); int cnt=2; while (rows.MoveNext()) { cnt++; String scnt = cnt.ToString(); string salesDescriptionValue = rows.Current.SelectSingleNode( "my:salesDescription", NamespaceManager).Value; salesDescriptionValue = "<html>" + salesDescriptionValue + "</html>";
// create the 3rd RTF's aFChunk text files //string uri =uri + cnt.ToString(); uri = uri + scnt;
Uri uri = new Uri("/salesDescription.txt", UriKind.Relative); string altChunkpart = altChunkpart + cnt.ToString(); PackagePart altChunkpart = packWordPrint.CreatePart(uri3, "application/xhtml+xml"); using (Stream fs = altChunkpart.GetStream()) { StreamWriter sw = new StreamWriter(fs); // write a line to the file string newLine = salesDescriptionValue; sw.WriteLine(newLine); sw.Close(); fs.Close(); } //for salesDescription RTF documentPart.CreateRelationship(uri3, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/" + "2006/relationships/aFChunk", "rId12"); }
Now, for the mishmash that does NOT work:
XPathNavigator domNav = MainDataSource.CreateNavigator(); XPathNodeIterator rows = domNav.Select( "/my:myFields/my:salesActivities/my:salesActivity", NamespaceManager); int cnt=2; while (rows.MoveNext()) { cnt++; String scnt = cnt.ToString(); string salesDescriptionValue = rows.Current.SelectSingleNode( "my:salesDescription", NamespaceManager).Value; salesDescriptionValue = "<html>" + salesDescriptionValue + "</html>";
// create the 3rd RTF's aFChunk text files //string uri =uri + cnt.ToString(); //uri = uri + scnt; produces error
Uri uri# = new Uri("/salesDescription.txt", UriKind.Relative); string altChunkpart = altChunkpart + cnt.ToString(); PackagePart altChunkpart = packWordPrint.CreatePart(uri#, "application/xhtml+xml"); using (Stream fs = altChunkpart.GetStream()) { StreamWriter sw = new StreamWriter(fs); // write a line to the file string newLine = salesDescriptionValue; sw.WriteLine(newLine); sw.Close(); fs.Close(); } //for salesDescription RTF documentPart.CreateRelationship(uri#, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/" + "2006/relationships/aFChunk", "rId2#"); }
I have Placed a # placeholder where I would like the string for the cnt to be substituted, if this is possible. Forgive my naivete in this realm.
Thanks for any help,
 Signature Joe
> Glad you finally got it solved! And well done! > [quoted text clipped - 197 lines] > > > > > > > > > > > > > > > > > > > > > > > > Joe S.Y.M. Wong-A-Ton - 11 Mar 2008 10:59 GMT It's difficult to jump in and understand the code you've written, but it looks like you want to dynamically rename a variable as in
Uri uri#
would become
Uri uri1 Uri uri2 etc.
If this is the case, I don't think it is necessary. The fact that you are using
Uri uri = new Uri()
within your loop should create a new Uri object every time in the loop, so you do not have to include the counter in the variable name. And appending the counter to "rId2" should not pose any issues. Or have I misunderstood the problem? --- S.Y.M. Wong-A-Ton
> I have encountered another bump in the road when I try to concatenate the > value of a counter to a label within a While loop (C#). Worse yet, [quoted text clipped - 248 lines] > > > > > > > > > > > > > > > > > > > > > > Thanks for your consideration. jogannon - 11 Mar 2008 15:08 GMT Theds are two generic questions then: 1) what is the preferred method for dynamically appending an int counter to a string variable?
2) I get an error if it is not Uri uri#, as within the loop:
Error 1 A local variable named 'uri' cannot be declared in this scope because it would give a different meaning to 'uri', which is already used in a 'parent or current' scope to denote something else
Thanks again.
 Signature Joe
> It's difficult to jump in and understand the code you've written, but it > looks like you want to dynamically rename a variable as in [quoted text clipped - 251 lines] > > > > > > > > > > > can then use normal System.IO classes to write that XHTML data to either a > > > > > > > > > > > Stream or a file. The contents of an RTF field in InfoPath is XHTML. This is S.Y.M. Wong-A-Ton - 12 Mar 2008 09:46 GMT 1. If you have a string variable called myString and a int variable called myInt, you would append them using myString + myInt.ToString(). If you have more strings to concatenate to each other, it is better to use the StringBuilder class.
2. Have you tried declaring the uri outside of the loop? As in Uri uri = null; while(...) { ... uri = new Uri(...) ... }
--- S.Y.M. Wong-A-Ton
> Theds are two generic questions then: > 1) what is the preferred method for dynamically appending an int counter to [quoted text clipped - 251 lines] > > > > > > > > > > > paste this to Word 2007 and save it as a .htm file. Should I include all of > > > > > > > > > > > the above, such as the namespace? jogannon - 12 Mar 2008 06:02 GMT Hi again, I just sent the code listing with comments and a description of the attempts to advance this work via the ASP Feedback site , but there was an application error experienced, followed by the standard apology. ask me if I bothered to say all that I wrote in my explanation. Of course not. Before I recompose and figure out how else to send the code listing, please advise if you received it despite the warning.
In essence, string arrays don't seem to work. There is an issue with the uri type (separate from string), my inability to convert from string to uri type with elements of array in the foreach. Apparently, the latter will cause a problem and that an 'event loop' may be best. It is surprising to see what little there is in C-sharpland for handling the issue of dynamic variable references within a loop, especially for uris.
Thanks again, and if you have any alternative mechanism for getting you the code listing ( I will also try to upload on your blog and hope it gets past the filters. Where this is not XML tagged, it may be alright.
 Signature Joe
> It's difficult to jump in and understand the code you've written, but it > looks like you want to dynamically rename a variable as in [quoted text clipped - 251 lines] > > > > > > > > > > > can then use normal System.IO classes to write that XHTML data to either a > > > > > > > > > > > Stream or a file. The contents of an RTF field in InfoPath is XHTML. This is S.Y.M. Wong-A-Ton - 12 Mar 2008 09:56 GMT I received your code, but not through ASPAlliance; thank you for that.
My time is extremely limited these days, Joe. Unless you can hold on until the end of April when I'll have some breathing room (before I dive into yet another busy period) to take a closer look at your code, it is best to continue trying out other methods and possibly also post your question in the .NET development newsgroup. I can only provide short and quick pointers at this time.
BTW, I'm not sure what you mean with 'event loop'? Did you read about this somewhere? --- S.Y.M. Wong-A-Ton
> Hi again, > I just sent the code listing with comments and a description of the attempts [quoted text clipped - 251 lines] > > > > > > > > > > > - <ul xmlns="http://www.w3.org/1999/xhtml" style="MARGIN-TOP: 0px; > > > > > > > > > > > MARGIN-BOTTOM: 0px" type="disc"> jogannon - 13 Mar 2008 05:01 GMT No need ever to apologize, especially about precious time. I am similarly time challenged. Today was, nonetheless, a break-thru day. With some serious C# SME help, and some tutoring along the way, we managed to get the C# code to do what is expected. Now I will turn my attention to the other side of the equation and get the aFChunks properly referenced in the .xsl and rendering well in the Word .docx. Will advise when it is all working--end to end--and send the whole solution to you. Give me a while longer to gather it all together, with notes to explain the steps.
Later, and good luck with your own endeavors.
 Signature Joe
> I received your code, but not through ASPAlliance; thank you for that. > [quoted text clipped - 248 lines] > > > > > > > > > > > > 1. Create a rtf file (test.rtf) and place along with [Content_Types].xml > > > > > > > > > > > > file or in a folder S.Y.M. Wong-A-Ton - 14 Mar 2008 08:15 GMT Thanks, Joe; I'll need it. I'm happy to hear you've got a "support system" to chip in and help. And take all the time you need to gather the info. --- S.Y.M. Wong-A-Ton
> No need ever to apologize, especially about precious time. I am similarly > time challenged. Today was, nonetheless, a break-thru day. With some [quoted text clipped - 247 lines] > > > > > > > > > > > > BODY etc. I'm not sure what the exact specs are for XHTML, but you should be > > > > > > > > > > > > able to find them on www.w3.org. First try it without any extra tags, and if
|
|
|