<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
    <channel>
        <title>Michael Bevels - Blogs at Near Infinity</title>


        <link>http://www.nearinfinity.com/blogs/</link>
        <description>Employee Blogs</description>
        <language>en</language>
        <copyright>Copyright 2011</copyright>
        <lastBuildDate>Wed, 09 Mar 2011 22:21:41 -0500</lastBuildDate>
        <generator>http://www.sixapart.com/movabletype/</generator>
        <docs>http://www.rssboard.org/rss-specification</docs>
        
        <item>
            <title>Simple Steps For Generating Word XML</title>
            <description><![CDATA[<br />This is a follow-up to my last post about Exporting an ExtJs GridPanel to Word XML.&nbsp; In that post I showed how to get all the configuration and state properties from an ExtJs GridPanel.&nbsp; This post will demonstrate how to generate a basic table within a Word XML document using Ruby to produce XML<br /><br /><b>Section 1: Building a sample</b><br /><br />The first step is to open Word, Open Office, or anything that will generate Open XML.&nbsp; If you're not an Open XML expert, you can create a sample document of what you want the final product to look like.&nbsp; Once you've got it formatted, save it in XML format.&nbsp; I suggest labeling everything so it's easy to find in the XML later.&nbsp; For example, if you're creating a table it might look like this:<br /><br />Header 1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; | Header 2&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; | Header 3<br />Row 1, Col 1 | Row 1, Col 2 | Row 1, Col 3<br />Row 2, Col 1 | Row 2, Col 2 | Row 2, Col 3<br /><br />There are three columns with names Header 1, Header 2, and Header 3.&nbsp; The data resides below these headers in Row 1 and Row 2.<br /><br /><b>Section 2: Building templates</b><br /><br />The next step is to start building templates.&nbsp; If you're just building an XML document with a simple table, you can use three simple templates: document, table, and row.<br /><br />The "document" template can contain everything outside the of the content of &lt;w:body&gt; tags which will be generated by the Ruby code in Section 3.&nbsp; This document template defines the fonts, styles, and document properties used by the sample generated in section 1.<br /><br /><i>document-template.xml</i> - Note that the "{table}" string will be replaced with the generated table template.<br /><br />
<pre class="prettyprint">&lt;?mso-application progid="Word.Document"?&gt;<br />&lt;w:wordDocument xml:space="preserve" w:embeddedObjPresent="no"&gt;<br />&lt;o:DocumentProperties&gt;...&lt;/o:DocumentProperties&gt;<br />&lt;o:CustomDocumentProperties&gt;...&lt;/o:CustomDocumentProperties&gt;<br />&lt;w:fonts&gt;...&lt;/w:fonts&gt;<br />&lt;w:lists&gt;...&lt;/w:lists&gt;<br />&lt;w:styles&gt;...&lt;/w:styles&gt;<br />&lt;w:docPr&gt;...&lt;/w:docPr&gt;<br />&lt;w:body&gt;{table}&lt;/w:body&gt;<br />&lt;/w:wordDocument&gt;<br /></pre><br /><i>table-template.xml</i> - Note that the "{rows}" string will be replaced with the generated rows template.&nbsp; If you're familiar with html tables, you should be able to recognize some patterns here.<br /><br />&lt;w:tbl&gt; defines a table.&nbsp; &lt;w:tr&gt; defines a row.&nbsp; &lt;w:tc&gt; defines a cell.&nbsp; Everything in between specifies the formatting.<br /><pre class="prettyprint">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;w:tbl&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tblPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tblStyle w:val="Table1"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tblW w:w="9973.2467" w:type="dxa"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tblInd w:w="0" w:type="auto"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:jc w:val="left"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tblPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tblGrid&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:gridCol w:w="3324.3676"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:gridCol w:w="3324.3676"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:gridCol w:w="3324.3676"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tblGrid&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:trPr/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tc&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcW w:type="dxa" w:w="3324.3676"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcMar/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcBorders&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:top w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:bottom w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:left w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:right w:val="none" w:sz="0" w:color="auto"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tcBorders&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tcPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pStyle w:val="Table_20_Contents"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:r&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:t&gt;Header 1&lt;/w:t&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:r&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tc&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tc&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcW w:type="dxa" w:w="3324.3676"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcMar/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcBorders&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:top w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:bottom w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:left w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:right w:val="none" w:sz="0" w:color="auto"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tcBorders&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tcPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pStyle w:val="Table_20_Contents"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:r&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:t&gt;Header 2&lt;/w:t&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:r&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tc&gt;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; #another w:tc defined here for Header 3...<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tr&gt;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {rows}<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/w:tblPr&gt;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pStyle w:val="Standard"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:sectPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:type w:val="next-page"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pgSz w:w="12241.5302" w:h="15841.9803" w:orient="portrait"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pgMar w:top="1133.9978" w:bottom="1133.9978" w:left="1133.9978" w:gutter="0" w:right="1133.9978"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pgBorders w:offset-from="text"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:sectPr&gt;<br /></pre><br /><i>row-template.xml</i> - Note that the "{column_#_value}" strings will be replaced with the corresponding values for the row being generated.<br /><br /><pre class="prettyprint">            &lt;w:tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:trPr/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tc&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcW w:type="dxa" w:w="3324.3676"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcMar/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcBorders&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:top w:val="none" w:sz="0" w:color="auto"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:bottom w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:left w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:right w:val="none" w:sz="0" w:color="auto"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tcBorders&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tcPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pStyle w:val="Table_20_Contents"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:r&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:t&gt;{column_1_value}&lt;/w:t&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:r&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tc&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tc&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcW w:type="dxa" w:w="3324.3676"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcMar/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:tcBorders&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:top w:val="none" w:sz="0" w:color="auto"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:bottom w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:left w:val="single" w:sz="0" w:color="000000"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:right w:val="none" w:sz="0" w:color="auto"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tcBorders&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tcPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:pStyle w:val="Table_20_Contents"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:pPr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:r&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;w:t&gt;{column_2_value}&lt;/w:t&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:r&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tc&gt;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #another w:tc defined with {column_3_value}...<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/w:tbl&gt;</pre><br /><b>Section 3:&nbsp; Injecting data into the templates and creating an XML file</b><br /><br />The code snippet below queries for some data. It loops over the "table_data" returned and builds rows based on the row-template.xml defined in section 2.&nbsp; The rows are concatenated and injected into the table template, which in turn is injected into the document template.&nbsp; Obviously some of of these steps are unnecessary (the table template could be a part of the document template, thus skipping a substitution), but I wanted to show that you can make templates as granular as you like.&nbsp; In my own solution, I have templates for cells, header rows, and much more.&nbsp; I used the configuration and state data of the ExtJs GridPanel (described in a previous blog post) and looped over column names and values to generate a table from scratch.&nbsp; However, most of the work in this blog post is already done for you.<br /><br />Depending on the size of your dataset, you may want to write periodically to the file.&nbsp; Holding many iterations of row-template.xml in memory can be costly.<br /><pre class="prettyprint"><br />#create a new empty xml document<br />document = File.new(some_filename, 'a')<br /><br />#query for data<br />table_data = SomeObject.find(:all, :conditions =&gt; 'some conditions...')<br /><br />document_template = File.open('path/to/document-template.xml').read<br /><br />table_template = File.open('path/to/table-template.xml').read<br />rows = []<br />table_data.each do |row_data|<br />&nbsp;&nbsp;&nbsp; row_template = File.open('path/to/row-template.xml').read<br />&nbsp;&nbsp;&nbsp; row_template.gsub!('{column_1_value}', row_data.col_1) #substitute in whatever returns the data you need to put in the Col 1 column.<br />&nbsp;&nbsp;&nbsp; row_template.gsub!('{column_2_value}', row_data.col_2) #substitute in whatever returns the data you need to put in the Col 2 column.<br />&nbsp;&nbsp;&nbsp; row_template.gsub!('{column_3_value}', row_data.col_3) #substitute in whatever returns the data you need to put in the Col 3 column.<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; #add the row to the master array of rows<br />&nbsp;&nbsp;&nbsp; rows &lt;&lt; row_template<br />end<br /><br />#substitute the dynamically generated rows into the table template<br />table_template.gsub!('{rows}', rows.join(''))<br /><br />#substitute the dynamically generated table into the document template<br />document_template.gsub!('{table}', table)<br /><br />#write everything to the new xml document.&nbsp; As I said before you'll probably want to write to the xml document more frequently than <br />#this example to avoid Out-Of-Memory errors.<br />document.puts document_template<br />document.close</pre><br /><br />As you can see, this is a very basic example.&nbsp; However, the same principals can be applied to much more complex and dynamic situations such as a exporting a fully user-configurable ExtJs GridPanel to Word XML.&nbsp; This process can also be applied to generating Excel XML files.<br />]]></description>
            <link>http://www.nearinfinity.com/blogs/michael_bevels/simple_steps_for_generating_wo.html</link>
            <guid>http://www.nearinfinity.com/blogs/michael_bevels/simple_steps_for_generating_wo.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Ruby</category>
            
            
            <pubDate>Wed, 09 Mar 2011 22:21:41 -0500</pubDate>
        </item>
        
        <item>
            <title>Exporting an ExtJs GridPanel to Word XML</title>
            <description><![CDATA[This blog post will lay out some of steps for exporting an ExtJs GridPanel to Word XML.&nbsp; This is useful if you want to save or print what's currently displayed in the grid.&nbsp; I am writing a subsequent post with steps on how to actually generate a Word XML file, but for now I'll focus on defining a grid, getting the grid's state, sending the grid's state to a controller, and prompting the user to save the generated Word XML document.<br /><br />Technologies used:<br />- Ruby on Rails<br />- mod_xsendfile for Apache2/Apache2.2<br />- ExtJs<br />- javascript<br /><br />At a high level, the following happens:<br />1. Gather and send the GridPanel state/configuration to the controller.<br />2. The controller runs a query and generates Word XML based on the query results.<br />3. The Word XML file is presented to the user via an "Open/Save As" dialog using XSendFile.<br /><br /><font style="font-size: 1.25em;"><b>Section 1: Getting the current state/configuration of the GridPanel</b></font><br /><br />If you're familiar with ExtJs GridPanel's you know they can be configured by each user viewing the panel.&nbsp; Columns can be added, removed, grouped, shortened, lengthened and repositioned.&nbsp; To capture the GridPanel's current state and pass it to the exporter, I wrote the following javascript.&nbsp; It calculates and returns an array containing the column order, which column data indexes belong to which titles, the grouped field (if any), the sorted field, the sorted direction, and the widths of each column.&nbsp; You will see where this function is used when I define the GridPanel in the next section.<br /><br /><br />
<pre class="prettyprint">var prepareExport = function(gridStore, gridColumnModel) {<br />&nbsp;&nbsp;&nbsp; var sort = null;<br />&nbsp;&nbsp;&nbsp; var direction = null;<br />&nbsp;&nbsp;&nbsp; if (gridStore.getSortState()) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sort = gridStore.getSortState().field();<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; direction = gridStore.getSortState().direction;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; var columnOrder = []; //ordered list of columns reflecting the GridPanel's state<br />&nbsp;&nbsp;&nbsp; var columnsToTitles = {}; //map of ext field mappings to column titles<br />&nbsp;&nbsp;&nbsp; var columnsToWidths = {}; //width of each column<br />&nbsp;&nbsp;&nbsp; var totalWidth = 0;<br />&nbsp;&nbsp;&nbsp; var groupByField = gridStore.groupField; //the store's current grouping field ('false' if not grouped)<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; var storeReaderMapping = gridStore.fields.items;<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //check to see if the groupField has a corresponding mapping<br />&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; gridReaderMapping.length; i++) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (gridReaderMapping[i].name == gridStore.groupField &amp;&amp; gridReaderMapping[i].mapping != null) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; groupByField = gridReaderMapping[i].mapping;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //get the total width of the displayed columns (this will be used later when generating the Word XML)<br />&nbsp;&nbsp;&nbsp; gridColumnModel.getColumnsBy(function(c) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (!c.hidden) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; totalWidth = totalWidth + c.width;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //iterate over the grid's column model.&nbsp; For displayed columns, get the ext field names (mappings) and column titles<br />&nbsp;&nbsp;&nbsp; gridColumnModel.getColumnsBy(function(c) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (!c.hidden) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; gridReaderMapping.length; i++) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (gridReaderMapping[i].name == c.dataIndex &amp;&amp; gridReaderMapping[i].mapping == null) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnOrder.push(gridReaderMapping[i].name);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var key = gridReaderMapping[i].name;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnsToTitles[key] = c.header;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnsToWidths[key] = c.width/totalWidth;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if (gridReaderMapping[i].name == c.dataIndex &amp;&amp; gridReaderMapping[i].mapping != null) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //if the name and mapping are different (i.e. a mapping exists), we need to push the mapping and not the name<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnOrder.push(gridReaderMapping[i].mapping);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var key = gridReaderMapping[i].mapping;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnsToTitles[key] = c.header;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; columnsToWidths[key] = c.width/totalWidth;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; return [columnOrder, columnsToTitles, groupByField, sort, direction, columnsToWidths];<br />};</pre><br /><br /><br /><font style="font-size: 1.25em;"><b>Section 2: The GridPanel</b></font><br /><br />Here's a basic ExtJs GridPanel.&nbsp; Note the "exportButton" is defined in Section 3.<br /><br /><pre class="prettyprint">var gridReaderMapping = [<br />&nbsp;&nbsp;&nbsp; {name: 'id'},<br />&nbsp;&nbsp;&nbsp; {name: 'col_one'},<br />&nbsp;&nbsp;&nbsp; {name: 'col_two', mapping: 'some_mapping'},<br />&nbsp;&nbsp;&nbsp; {name: 'col_three'}<br />];<br /><br />var gridColumnModel = new Ext.grid.ColumnModel({<br />&nbsp;&nbsp;&nbsp; defaults: {sortable: true},<br />&nbsp;&nbsp;&nbsp; columns: [<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {header: 'ID', dataIndex: 'id'},<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {header: 'Column One', dataIndex: 'col_one'},<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {header: 'Column Two', dataIndex: 'col_two'},<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {header: 'Column Three', dataIndex: 'col_three'}<br />&nbsp;&nbsp;&nbsp; ]<br />});<br /><br />var store = new Ext.data.GroupingStore({<br />&nbsp;&nbsp;&nbsp; proxy: new Ext.dataHttpProxy({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; url: 'give/me/my/data'<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; method: 'GET'<br />&nbsp;&nbsp;&nbsp; }),<br />&nbsp;&nbsp;&nbsp; reader: new Ext.data.JsonReader({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; root: 'data',<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; totalProperty: 'total',<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; messageProperty: 'message'<br />&nbsp;&nbsp;&nbsp; }, gridReaderMapping)<br />});<br /><br />var grid = new Ext.grid.GridPanel({<br />&nbsp;&nbsp;&nbsp; id: 'gridpanel',<br />&nbsp;&nbsp;&nbsp; ds: gridStore,<br />&nbsp;&nbsp;&nbsp; cm: gridColumnModel,<br />&nbsp;&nbsp;&nbsp; sm: new Ext.grid.RowSelectionModel({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; singleSelect: true<br />&nbsp;&nbsp;&nbsp; }),<br />&nbsp;&nbsp;&nbsp; tbar: [exportButton],<br />&nbsp;&nbsp;&nbsp; view: etc, etc, etc, etc...<br />});</pre><br /><br /><font style="font-size: 1.25em;"><b>Section 3: The Export Button</b></font><br /><br />When the export button is clicked it gathers all the necessary data from the GridPanel (columns, widths, etc) and passes that data along with query parameters to the controller.&nbsp; The controller runs a query and generates the Word XML file.&nbsp; Section 4 describes what happens when the Ajax request returns the data successfully.<br /><br />As I said at the beginning of this post, I will follow on with another post about the actual Word XML generation.&nbsp; The Word XML generation isn't too scary.&nbsp; If you're impatient, here are a few tips on Word XML generation.<br />&nbsp;&nbsp;&nbsp; 1. You can start by creating a small Word XML file with a single table using MS Word or Open Office.&nbsp; <br />&nbsp;&nbsp;&nbsp; 2. Open the XML file with the XML viewer/editor of your choice.&nbsp; Your table will be buried somewhere between &lt;w:body&gt; and &lt;/w:body&gt;.&nbsp; All the other sections of the XML can remain the same.&nbsp; <br />&nbsp;&nbsp;&nbsp; 3. You can create a series of templates for Word XML tables and rows based on the patterns you see in your Word XML sample.<br />&nbsp;&nbsp;&nbsp; 4. In your Word XML generator, substitute values into these templates to build tables.<br />&nbsp;&nbsp;&nbsp; 5. Insert the generated templates into a "master" template. <br /><br /><pre class="prettyprint">var exportButton = new Ext.Button({<br />&nbsp;&nbsp;&nbsp; renderTo: this.wrap,<br />&nbsp;&nbsp;&nbsp; listeners: {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; click: function (node, event) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var exportConfig = prepareExport(grid.getStore(), grid.getColumnModel());<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Ext.Ajax.request({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; url: 'url/to/query/for/data'<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; params: {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'columnsToTitles': Ext.util.JSON.encode(exportConfig[1]),<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'columnsToWidths': Ext.util.JSON.encode(exportConfig[5]),<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'columnOrder[]': exportConfig[0],<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'groupByExport': exportConfig[2],<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'groupBy': gridStore.groupField,<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'groupDir': 'ASC',<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'sort': exportConfig[3],<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'dir': exportConfig[4],<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'export': true<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 'query': build_some_query_params_to_pass_to_the_controller<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; },<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; success: function(response, opts) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; window.location.href = 'path/to/exporter_controller/export_word_XML'<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; },<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; failure: function(response, opts) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //output error message<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; },<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; scope: this<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }); <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />});</pre><br /><br /><font style="font-size: 1.25em;"><b>Section 4:&nbsp; Downloading the Word XML</b></font><br /><br />Using XSendFile to prompt the user with an "Open/Save As" dialog box.<br /><br /><pre class="prettyprint">class ExportController &lt; ApplicationController<br />&nbsp;&nbsp;&nbsp; def export_word_XML<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; filename = "#{X_SENDFILEPATH}/word_doc.xml"<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (File.exist?(filename))<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; send_file filename, :x_sendfile =&gt; true<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; render :nothing =&gt; true<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; end<br />&nbsp;&nbsp;&nbsp; end<br />end</pre><br />Stay tuned for the upcoming Word XML <b><i>generation</i></b> blog post!<br />]]></description>
            <link>http://www.nearinfinity.com/blogs/michael_bevels/exporting_an_extjs_gridpanel_t.html</link>
            <guid>http://www.nearinfinity.com/blogs/michael_bevels/exporting_an_extjs_gridpanel_t.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">JavaScript</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Ruby</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Web Development</category>
            
            
            <pubDate>Sun, 06 Mar 2011 16:43:27 -0500</pubDate>
        </item>
        
        <item>
            <title>JSF Editable Datatable</title>
            <description><![CDATA[<p>
I recently needed to create a  "JSF Editable Datatable" where all fields (or a subset) could be edited at once.  Here's what I came up with...
</p>

<p>
My requirements:
</p>

<ul>
<li>Use a standard JSF datatable.</li>
<li>When user clicks the Edit Button, all fields (or a subset) become editable inputText components.</li>
<li>When a user clicks the Save Button, the changes will be saved to the affected objects and persisted to the DB.</li>
</ul>

<p>
My implementation involves the following:
</p>


<ul>
<li>IceFaces, Hibernate, Spring.</li>
<li>1 jspx page with an ice:datatable component.</li>
<li>1 backing bean with edit and save actions for the datatable.</li>
</ul>

<p>
The jspx: <br /></p>
<pre class="prettyprint">&lt;jsp:root
        xmlns:jsp="http://java.sun.com/JSP/Page"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:c="http://java.sun.com/jstl/core"
        xmlns:ice="http://www.icesoft.com/icefaces/component"
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        version="2.0"&gt;
    &lt;jsp:directive.page contentType="text/html"/&gt;
    &lt;jsp:output omit-xml-declaration="no"
                doctype-root-element="html"
                doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
                doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/&gt;

    &lt;ice:dataTable id="editableDatatable" value="#{backingBean.elements}" var="element"&gt;
        &lt;ice:column&gt;
            &lt;f:facet name="header"&gt;
                &lt;ice:outputText value="Value 1"/&gt;
            &lt;/f:facet&gt;
            &lt;h:inputText disabled="#{backingbean.elementsDisabled}"
                         value="#{element.value1}"/&gt;
        &lt;/ice:column&gt;
        &lt;ice:column&gt;
            &lt;f:facet name="header"&gt;
                &lt;ice:outputText value="Value 2"/&gt;
            &lt;/f:facet&gt;
            &lt;h:inputText disabled="#{backingbean.elementsDisabled}"
                         value="#{element.value2}"/&gt;
        &lt;/ice:column&gt;
    &lt;/ice:dataTable&gt;

    &lt;br/&gt;

    &lt;!--Buttons will be hidden or visible based on whether the table is in edit mode or display mode--&gt;
    &lt;div id="editElement" style="display:block;"&gt;
        &lt;!--Put the table in edit mode by enabling the inputtext components--&gt;
        &lt;ice:commandButton value="Edit Element" partialSubmit="true"
                           onclick="toggleLayerOn('updateElement');toggleLayerOff('editElement');"&gt;
            &lt;f:setPropertyActionListener value="#{false}" target="#{backingBean.elementsDisabled}"/&gt;
        &lt;/ice:commandButton&gt;
    &lt;/div&gt;
    &lt;div id="updateElement" style="display:none;"&gt;
        &lt;!--Save the changes and return to display mode--&gt;
        &lt;ice:commandButton action="#{backingBean.updateElementValues}" value="Update Element Values"
                           partialSubmit="true"
                           onclick="toggleLayerOn('editElement');toggleLayerOff('updateElement');"/&gt;
        &lt;!--Cancel the changes and return to display mode--&gt;
        &lt;ice:commandButton value="Cancel Changes" partialSubmit="true"
                           onclick="toggleLayerOn('editElement');toggleLayerOff('updateElement');"&gt;
            &lt;f:setPropertyActionListener value="#{true}" target="#{backingBean.elementsDisabled}"/&gt;
        &lt;/ice:commandButton&gt;
    &lt;/div&gt;

&lt;/jsp:root&gt;
</pre>





<p>
The backing bean.  Please note the upateElementValues() method.  This gets the editableDataTable from the FacesContext, casts it to an HtmlDataTable, loops over the rows of this datatable, and casts each row to an Element.  These Elements contain the updated values entered by the user.  You must then load the original Elements via Id and make the necessary changes before persisting the updates back to the database.  Make sure to set your datatable rowIndex back to -1 (see code) or there will be JSF errors.
</p>
<pre class="prettyprint">import com.icesoft.faces.component.ext.HtmlDataTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.context.FacesContext;
import java.util.*;

public class BackingBean {

    public static final Logger log = LoggerFactory.getLogger(BackingBean.class);

    private ElementDao elementDao;
    private boolean elementsDisabled = true;
    private List&lt;Element&gt; elements = new ArrayList&lt;Element&gt;();

    public BackingBean() {
        >//get all the elements from the database
        elements = elementDao.getAllElements();
    }

    public void setElementDao(ElementDao elementDao) {
        this.elementDao = elementDao;
    }

    public void updateElementValues() {
        >//get the datatable as a UI component
        UIComponent comp = FacesContext.getCurrentInstance().getViewRoot().findComponent("editableDataTable");

        if (comp != null) {
            UIData uIData = (UIData) comp;
            HtmlDataTable myTable = (HtmlDataTable) uIData;

            for (int i = 0; i &lt; myTable.getRowCount(); i++) {
                >//loop over the rows
                myTable.setRowIndex(i);
                >//get the values that the user edited for this row
                Element modifiedElement = (Element) myTable.getRowData();
                >//print the values to verify they are correct
                log.info("Value 1 " + modifiedElement.getValue1());
                log.info("Value 2 " + modifiedElement.getValue2());

                >//load the element from the database
                Element originalElement = elementDao.load(modifiedElement.getId());
                originalElement.setValue1(modifiedElement.getValue1());
                originalElement.setValue2(modifiedElement.getValue2());
                >//update the values in the database for the given element
                elementDao.update(originalElement);

            }
            >//make sure to set the row Index back to -1!!!
            myTable.setRowIndex(-1);
        }
        >//disable the inputtext components, they should only be enabled during "edit mode"
        setElementsDisabled(true);
    }

    public boolean isElementsDisabled() {
        return elementsDisabled;
    }

    public void setElementsDisabled(boolean elementsDisabled) {
        this.elementsDisabled = elementsDisabled;
    }

    public List&lt;Element&gt; getElements() {
        return elements;
    }

    public void setElements(List&lt;Element&gt; elements) {
        this.elements = elements;
    }
}</pre>


<p>
The object:
</p>
<pre class="prettyprint">import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.Column;

public class Element {

    @Id
    @GeneratedValue(generator = "hibernate-uuid")
    private String id;

    @Column(nullable = false)
    private String value1;

    @Column(nullable = false)
    private String value2;

    public Element(String value1, String value2) {
        this.value1 = value1;
        this.value2 = value2;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getValue1() {
        return value1;
    }

    public void setValue1(String value1) {
        this.value1 = value1;
    }

    public String getValue2() {
        return value2;
    }

    public void setValue2(String value2) {
        this.value2 = value2;
    }
}
</pre>]]></description>
            <link>http://www.nearinfinity.com/blogs/michael_bevels/jsf_editable_datatable.html</link>
            <guid>http://www.nearinfinity.com/blogs/michael_bevels/jsf_editable_datatable.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">General</category>
            
            
            <pubDate>Tue, 26 Aug 2008 15:55:31 -0500</pubDate>
        </item>
        
        <item>
            <title>JSF - Dynamically Adding UIComponents To A Form</title>
            <description><![CDATA[<p>
Here's a quick and easy way to dynamically add JSF components to a page.  You'll need a jsp, a backing bean, and a jsf component library.  On the jsp, you will need a button and "container component" (I used a PanelGrid) with a binding to a backing bean.  The button will call a method on the backing bean.  The method will add child UI components to the bound container component.
</p>

<p>
1.  The jsp.  Notice the container component (PanelGrid) has a binding to the backing bean.  The button calls the "addComponents" method on the backing bean.
</p>

<pre class="prettyprint">&lt;html xmlns:jsp="http://java.sun.com/JSP/Page"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:c="http://java.sun.com/jstl/core"
      xmlns:ice="http://www.icesoft.com/icefaces/component"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;jsp:directive.page contentType="text/html"/&gt;

&lt;ui:composition&gt;


    &lt;ice:panelGrid binding="#{backingBean.containerComponent}"/&gt;

    &lt;br/&gt;

    &lt;ice:commandButton value="Add UI Components" action="#{backingBean.addComponents}" partialSubmit="true"/&gt;

&lt;/ui:composition&gt;
&lt;/html&gt;</pre>

<p>
2.  The backing bean.  The addComponents method makes a call to a database to determine what/how many fields need to be added to the container component.
</p>

<pre class="prettyprint">import com.icesoft.faces.component.ext.HtmlPanelGrid;
import com.icesoft.faces.component.ext.UIColumn;
import com.icesoft.faces.component.ext.HtmlOutputText;
import com.icesoft.faces.component.ext.HtmlInputText;

public class BackingBean {

    private HtmlPanelGrid containerComponent;

    public void addComponent() {
        //clean previous component
        containerComponent.getChildren().clear();

        List&lt;Node&gt; nodes = nodeDao.getAllNodes();

        //dynamically add Child Components to Container Component
        for (Node node : nodes) {
            UIColumn col = new UIColumn();
            HtmlOutputText ot = new HtmlOutputText();
            ot.setValue(node.getLabel() + ": ");
            col.getChildren().add(ot);
            HtmlInputText it = new HtmlInputText();
            it.setValue("");
            it.setId(node.getLabel());
            col.getChildren().add(it);

            if (containerComponent == null) {
                containerComponent = new HtmlPanelGrid();
            }
            containerComponent.getChildren().add(col);
        }

    }

    public HtmlPanelGrid getContainerComponent() {
        return containerComponent;
    }

    public void setContainerComponent(HtmlPanelGrid containerComponent) {
        this.containerComponent = containerComponent;
    }
}
</pre>

<p>
That's it!
</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/michael_bevels/dynamic_forms_using_jsf.html</link>
            <guid>http://www.nearinfinity.com/blogs/michael_bevels/dynamic_forms_using_jsf.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">General</category>
            
            
            <pubDate>Mon, 21 Jul 2008 10:25:40 -0500</pubDate>
        </item>
        
        <item>
            <title>Dynamic Trees in JSF - The Easy Way</title>
            <description><![CDATA[<p>
Another JSF project I've been working on required another dynamic JSF tree.  However, this time the component library being used was IceFaces.  If you recall, the last time I used RichFaces.  I have to say that using IceFaces made this task MUCH easier.
</p>

<p>
The basic setup:
</p>

<ul>
<li>
A "tree" structure that is made up of "node" objects.  Each node has a parent node as well as a list of child nodes.  Root nodes have a null parent.  The tree object takes a list of root nodes.  (see code below)
</li>
<li>
A JSF Tree.  IceFaces was used this time. (see code below)
</li>
<li>
A JSF managed backing bean with ActionListeners and DAO access.  ActionListeners are used for the CRUD operations on nodes.  DAO access is used for directly updating the objects in the database. (see code below)
</li>
<li>
A great place to start is with one of IceFaces tree examples.  I used this one: <a href="http://facestutorials.icefaces.org/tutorial/tree-tutorial.html#dynamicallychangingatree">IceFaces Sample Tree Application</a>
</li>
</ul>

<p>
All of this sounds very familiar, right?  
</p>

<p>
Here's where it starts to get different.  
</p>

<p>
The Tree UI:
</p>

<pre class="prettyprint">&lt;ice:panelGroup style="border: 1px solid gray;"&gt;
                &lt;ice:tree id="tree"
                          value="#{tree.model}"
                          var="item"
                          hideRootNode="false"
                          hideNavigation="false"
                        &gt;
                    &lt;ice:treeNode&gt;
                        &lt;f:facet name="content"&gt;
                            &lt;ice:panelGroup style="display: inline"&gt;
                                &lt;ice:commandLink
                                        actionListener="#{item.userObject.nodeClicked}"
                                        value="#{item.userObject.label}"/&gt;
                            &lt;/ice:panelGroup&gt;
                        &lt;/f:facet&gt;
                    &lt;/ice:treeNode&gt;
                &lt;/ice:tree&gt;
            &lt;/ice:panelGroup&gt;</pre>

<p>
Note that "tree.model" is passed in.  Also note that there is a commandLink with actionListener.  This sets the selected node id on the backing bean.  Both of these things can be seen in the IceFaces sample tree application referenced above.
</p>

<p>
What you'll need to do to make this truly dynamic is add some controls to your tree display page and some backing bean methods.  I'll use adding a node as an example.
</p>

<p>
Add the code below to the page that displays the tree.  newNodeName is a field on the backing bean.  addChildToSelectedNode is the method on the backing bean that takes "newNodeName", creates a node, and persists it to the database.    
</p>

<pre class="prettyprint">&lt;div id="addNode"&gt;
    &lt;table width="100%"&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;ice:outputText value="Name:"/&gt;&lt;/td&gt;
            &lt;td&gt;&lt;ice:inputText value="#{nodeManagement.newNodeName}"/&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;
                &lt;ice:commandButton 
                                   value="Add Child to Selected Node"
                                   action="#{nodeManagement.addChildToSelectedNode}"
                                   partialSubmit="true"/&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
&lt;/div&gt;

&lt;ice:outputText
        value="Selected Node: #{tree.selectedNodeObject.label}"
        escape="false" style="font-weight:bold;"/&gt;</pre>

<p>
The method that add a node to the tree is shown below.  Note the last line (tree.buildTreeModel()).  This rebuilds the tree model that used to display the tree.  If this method is not implemented on the Tree bean, you will have to refresh the page manually to see the node that was just created.
</p>

<pre class="prettyprint">    public void addNodeToSelectedNode() {
        //you'll probably want to handle errors here
        //selectedNodeId can't be blank or null
        //newNodeName shouldn't be blank or null

        Node newNode = new Node();
        
        //load the selectedNode using the selectedNodeId
        Node selectedNode = nodeDao.load(selectedNodeId);
        
        //get the selected node's Set of children
        Set&lt;Node&gt; childrenOfParent = selectedNode.getChildren();

        //create node to be added
        newNode.setChildren(null);
        newNode.setLabel(newNodeName);
        newNode.setParent(selectedNode);

        //add new node to selectedNode
        childrenOfParent.add(newNode);

        //saving selected node saves selectedNode as well as newNode
        nodeDao.save(selectedNode);

        //rebuild tree
        tree.buildTreeModel();
    }</pre>


<p>The node: (more of the same from last time)</p>

<pre class="prettyprint">import javax.persistence.*;
import java.util.List;
import org.hibernate.annotations.GenericGenerator;

@Entity
@GenericGenerator(
        name = "hibernate-uuid", strategy = "uuid"
)
public class Node {
    @Id
    @GeneratedValue(generator = "hibernate-uuid")
    private String id;

    @Column(nullable = false)
    private String label;

    @OneToMany(mappedBy = "parent", cascade = {CascadeType.ALL})
    private List<node> children;

    @ManyToOne
    @JoinColumn(name = "fk_parent_id")
    private Node parent;

   // Getters and Setters...
}
</node></pre>

<p>
I think is a much more straight forward way of creating a dynamic JSF tree.  Using the <a href="http://facestutorials.icefaces.org/tutorial/tree-tutorial.html#dynamicallychangingatree">IceFaces Sample Application</a> is a good starting point.  Adding the few snippets of code I've provided above should get you the rest of the way.
</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/michael_bevels/dynamic_trees_in_jsf_the.html</link>
            <guid>http://www.nearinfinity.com/blogs/michael_bevels/dynamic_trees_in_jsf_the.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">General</category>
            
            
            <pubDate>Tue, 17 Jun 2008 08:50:12 -0500</pubDate>
        </item>
        
        <item>
            <title>Passing Params to a New Window with JSF</title>
            <description><![CDATA[<p><b>Here's what I wanted to accomplish:</b></p>

<p>A user performs a search.  The user sees a list of results.  The user clicks on a "details" link for a single record in the list of results.  The action of clicking on the details link launches a popup window that displays the details of the record selected.</p>

<p><b>Here's how I thought it should work:</b></p>

<p>The page with the list of results and the details popup page would share the same backing bean.  Each "details" link (commandLink, commandButton, outputLink...doesn't matter) in the list of results would use f:setPropertyActionListener to set the "selectedRecordId" on the backing bean.  An onclick event on the details link would launch a popup window.  The popup window would get the "selectedRecordId" from the shared backing bean along with other data relating to the selected record.</p>

<p>Sounds pretty straight forward, right?  Wrong.  The problem is that any javascript events are executed before the form is submitted.  So in the situation described above, the popup launches first and THEN the setProperty ActionListener sets selectedRecordId on the backing bean.  When the popup window loads, it can't retrieve selectedRecordId because it hasn't been set yet.</p>

<p><b>A Solution!</b></p>

Here's a high level overview of how it works.  The javascript on the details link passes the recordId on the URL.  When the details popup page accesses the "selectedRecordId" on the backing bean, the getter for this field calls a method which retrieves the value of "recordId" that was passed on the URL.  This value can then be set to "selectedRecordId" on the backing bean.  Both the page with the dataTable results and the details popup page now have access to "selectedRecordId".

<p><b>The Code!</b></p>

<p>I used icefaces in the example code below.</p>

<p>The dataTable with details popup link:</p>
<pre class="prettyprint">&lt;ice:dataTable id="searchResults" value="#{basicSearch.records}" var="item"&gt;
    &lt;ice:column&gt;
        &lt;f:facet name="header"&gt;
            &lt;ice:commandSortHeader
                    columnName="#{basicSearch.labelColumnName}"
                    arrow="true"&gt;
                &lt;ice:outputText value="#{basicSearch.labelColumnName}"/&gt;
            &lt;/ice:commandSortHeader&gt;
        &lt;/f:facet&gt;
        &lt;ice:outputText value="#{item.label}"/&gt;
    &lt;/ice:column&gt;

    &lt;ice:column&gt;
        &lt;f:facet name="header"&gt;
            &lt;ice:outputText value="Details"/&gt;
        &lt;/f:facet&gt;

        &lt;ice:commandButton image="/resources/images/icon_small_info.gif"
                           onclick="doPopup('#{request.contextPath}/recordDetails/details.jspx?recordId=#{item.recordId}'); "&gt;
        &lt;/ice:commandButton&gt;
    &lt;/ice:column&gt;
&lt;/ice:dataTable&gt;</pre> 

<p>The important stuff from the backing bean:</p>
<pre class="prettyprint">    private String selectedRecordId;

    public String getSelectedRecordId() {
        selectedRecordId = (String) getParamValue("#{param.recordId}");
        return selectedRecordId;
    }

    public void setSelectedRecordId(String selectedRecordId) {
        this.selectedRecordId = selectedRecordId;
    }

    public Object getParamValue(String s) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        Object value = facesContext.getApplication().createValueBinding(s).getValue(facesContext);
        return value;
    }</pre>

<p>The javascript:</p>
<pre class="prettyprint">function doPopup(source) {
    popup = window.open(source, "popup", "height=600,width=900)");
    popup.focus();
}</pre>

<p>Accessing the recordId from the popup window:</p>
<pre class="prettyprint">&lt;ice:outputText  value="#{metadataView.selectedRecordId}"/&gt;</pre>

<p>Concurrent DOM Access so both windows can access the same backing bean: (web.xml)</p>
<pre class="prettyprint">    &lt;context-param&gt;
        &lt;param-name&gt;com.icesoft.faces.concurrentDOMViews&lt;/param-name&gt;
        &lt;param-value&gt;true&lt;/param-value&gt;
    &lt;/context-param&gt;</pre>]]></description>
            <link>http://www.nearinfinity.com/blogs/michael_bevels/passing_params_to_a_new.html</link>
            <guid>http://www.nearinfinity.com/blogs/michael_bevels/passing_params_to_a_new.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">General</category>
            
            
            <pubDate>Wed, 23 Apr 2008 14:35:33 -0500</pubDate>
        </item>
        
        <item>
            <title>Dynamic Trees in JSF</title>
            <description><![CDATA[<p>
A JSF project that I've been working on required a dynamic tree.  Not just a tree that loads dynamically, but a tree that a user can perform CRUD operations on and instantly see the changes they've made.  I'm going to walk through an example of how to accomplish this.
</p>

<p>
The basic setup:
</p>

<ul>
<li>
A "'tree" structure that is made up of "node" objects.  Each node has a parent node as well as a list of child nodes.  Root nodes have a null parent.  The tree object takes a list of root nodes.  (see code below)
</li>
<li>
A JSF Tree.  I used the RichFaces tree because RichFaces was already being used throughout the application, but this can be applied to other JSF trees as well. (see code below)
</li>
<li>
A JSF managed backing bean with ActionListeners and DAO access.  ActionListeners are used for the CRUD operations on nodes.  DAO access is used for directly updating the objects in the database. (see code below)
</li>
</ul>

<p>The node:</p>

<pre class="prettyprint">import javax.persistence.*;
import java.util.List;
import org.hibernate.annotations.GenericGenerator;

@Entity
@GenericGenerator(
        name = "hibernate-uuid", strategy = "uuid"
)
public class Node {
    @Id
    @GeneratedValue(generator = "hibernate-uuid")
    private String id;

    @Column(nullable = false)
    private String label;

    @OneToMany(mappedBy = "parent", cascade = {CascadeType.ALL})
    private List<node> children;

    @ManyToOne
    @JoinColumn(name = "fk_parent_id")
    private Node parent;

   // Getters and Setters...
}</node></pre>

<p>The tree:</p>
<pre class="prettyprint">&lt;rich:tree id="tree" ajaxSubmitSelection="true" switchType="client" onselected="return false;"&gt;
    &lt;rich:recursiveTreeNodesAdaptor var="node" roots="#{treeCreator.rootNodes}" nodes="#{node.getChildren}"&gt;
        &lt;rich:treeNode data="#{node.id}"&gt;
            &lt;!--Node Name--&gt;
            &lt;h:outputText value="#{node.label}" /&gt;

            &lt;!-- Control Buttons --&gt;
            &lt;!--Button used to toggle addNode Div --&gt;
            &lt;input type="image" value="Add Child" title="Add Child"
                   onclick="toggleLayer('addNode#{node.id}');return false;"
                   src="resources/images/controls_addlevel.gif"/&gt;
            &lt;!--Button used to toggle editNode Div --&gt;
            &lt;input type="image" value="Edit Node" title="Edit Node"
                   onclick="toggleLayer('editNode#{node.id}');return false;"
                   src="resources/images/controls_edit.gif"/&gt;
            &lt;!--Button for Deleting node --&gt;
            &lt;a4j:commandButton actionListener="#{treeCreator.deleteNode}"
                               data="#{node.id}" value="Delete Node" reRender="tree"
                               image="/resources/images/controls_delete.gif"
                               title="Delete Node"
                               onclick="if(!confirm('Delete Node?')){ return; };"/&gt;


            &lt;!-- Divs for name entry/edit--&gt;
            &lt;div id="addNode#{node.id}" style="display:none;"&gt;
                &lt;h:outputText value="Node Name: "/&gt;
                &lt;h:inputText binding="#{treeCreator.nodeAdd}"/&gt;
                &lt;a4j:commandButton value="Save and Create" title="Save and Create"
                                   actionListener="#{treeCreator.addNode}"
                                   data="#{node.id}"
                                   onclick="toggleLayer('addNode#{node.id}');"
                                   image="/resources/images/icon_small_save.gif"
                                   reRender="tree"/&gt;
                &lt;input type="image" src="resources/images/icon_small_cancel.gif" value="Cancel"
                       onclick="toggleLayer('addNode#{node.id}');return false;" title="Cancel"/&gt;
            &lt;/div&gt;

            &lt;!--Div for Editing an Org --&gt;
            &lt;div id="editNode#{node.id}" style="display:none;"&gt;
                &lt;h:outputText value="New Node Name: "/&gt;
                &lt;h:inputText binding="#{treeCreator.editNode}"/&gt;
                &lt;a4j:commandButton value="Save Changes" title="Save Changes"
                                   actionListener="#{treeCreator.editNode}"
                                   data="#{node.id}"
                                   onclick="toggleLayer('editNode#{node.id}');"
                                   image="/resources/images/icon_small_save.gif"
                                   reRender="tree"/&gt;
                &lt;input type="image" src="resources/images/icon_small_cancel.gif" value="Cancel"
                       onclick="toggleLayer('editNode#{node.id}');return false;" title="Cancel"/&gt;
            &lt;/div&gt;
        &lt;/rich:treeNode&gt;
    &lt;/rich:recursiveTreeNodesAdaptor&gt;
&lt;/rich:tree&gt;
</pre>

<p>
*Note that toggleLayer() is a javascript function that hides/unhides the contents of a given div tag.
</p>
<p>
*Note that the inputText fields have bindings to the backing bean.
</p>

<p>The ActionListeners: </p>
<pre class="prettyprint"> public void addNode(ActionEvent event) {
        //get the button that fired the event   
        HtmlAjaxCommandButton button = (HtmlAjaxCommandButton) event.getComponent();
        //get ID of the parent Node - it's stored in the data attribute of the add button
        String parentNodeId = (String) button.getData();
        //get parent node object
        Node parentNode = nodeDao.getById(parentNodeId);
        //create new node object and set label, parent, children, etc
        Node nodeToAdd = new Node();
        nodeToAdd.setLabel((String) addNode.getValue());
        nodeToAdd.setParent(parentNode);
        nodeToAdd.setChildren(new HashSet<node>());
        parentNode.getChildren().add(nodeToAdd);
        //save node to DB
        nodeDao.saveOrUpdate(parentNode);
    }

    public void editNode(ActionEvent event) {
        //get the button that fired the event
        HtmlAjaxCommandButton button = (HtmlAjaxCommandButton) event.getComponent();
        //get ID of Node to edit - it's stored in the data attribute of the edit button
        String nodeId = (String) button.getData();
        //load node from DB
        Node nodeToEdit = nodeDao.getById(nodeId);
        //update node label from UI input
        nodeToEdit.setLabel((String) editNode.getValue());
        //update node label in DB
        nodeDao.update(nodeToEdit);
    }

    public void deleteNode(ActionEvent event) {
        //get ID of Node to delete - it's stored in the data attribute of the delete button
        HtmlAjaxCommandButton button = (HtmlAjaxCommandButton) event.getComponent();
        String nodeId = (String) button.getData();
        //get node object via Dao
        Node nodeToDelete = nodeDao.getById(nodeId);

        //set reference from parent to null
        Node parentNode = nodeToDelete.getParent();

        //don't delete the Root Node
        if (parentNode != null) {
            Set<node> childNodes = parentNode.getChildren();
            childNodes.remove(nodeToDelete);
            //put updated list of childNodes on parentNode
            parentNode.setChildren(childNodes);
            //save parentNode to DB
            nodeDao.save(parentNode);
            //set parent to null
            nodeToDelete.setParent(null);
            //delete the node from the DB
            nodeDao.delete(nodeToDelete);
        }
    }
</node></node></pre>

<p>The managed bean within faces config: </p>
<pre class="prettyprint">    &lt;managed-bean&gt;
        &lt;description&gt;
            Backing bean for the tree
        &lt;/description&gt;
        &lt;managed-bean-name&gt;treeCreator&lt;/managed-bean-name&gt;
        &lt;managed-bean-class&gt;path.to.the.TreeCreator&lt;/managed-bean-class&gt;
        &lt;managed-bean-scope&gt;request&lt;/managed-bean-scope&gt;
        &lt;managed-property&gt;
            &lt;property-name&gt;nodeDao&lt;/property-name&gt;
            &lt;value&gt;#{nodeDao}&lt;/value&gt;
        &lt;/managed-property&gt;
    &lt;/managed-bean&gt;</pre>

<p>
Here's how it all fits together using the Ã'Add ChildÃ" operation as an example:
</p>
<p>

</p><ol type="1">
<li>A user visits the tree page and sees the tree with a single root node:
<img src="http://www.nearinfinity.com/blogs/resources/mbevels/jsfTreePic1.jpg" />
</li>
<li>The user clicks the Ã'Add ChildÃ" button on the root node:
<img src="http://www.nearinfinity.com/blogs/resources/mbevels/jsfTreePic2.jpg" />
</li>
<ol type="A">
<li>
The Ã'addNode<nodeid>Ã" div is unhidden (via javascript) which displays an input text box, a save button, and a cancel button to the right of the root node.
</nodeid></li>
</ol>
<li>The user types in a name for the node and clicks the save button.  Note that the save button has a few attributes including actionListener=Ã"treeCreator.addNodeÃ" and data=Ã"#{node.id}Ã". 
</li>
<ol type="A">
<li>
The Ã'addNode<nodeid>Ã" div is hidden again (via javascript).
</nodeid></li>
<li>
The addNode ActionListener is called.  See the addNode ActionListener.
</li>
<ol type="i">
<li>
The save button is retrieved from the ActionEvent that was passed to this ActionListener.  The Ã'dataÃ" attribute stored on this save button is retrieved which contains the ID of the soon-to-be-parent node.  The parent node object is loaded via dao access.  A new node (with user specified name which is retrieved via binding of the inputText box to backing beans) is added to the parent's children list.  The parent node is saved which also saves the new child object to the database.
</li>
</ol>
</ol>
<li>The tree is refreshed and the new node appears.  Note that the tree "switchType" can be set to client, server, or ajax.  This will effect how the page refreshes and the tree loads.
<img src="http://www.nearinfinity.com/blogs/resources/mbevels/jsfTreePic3.jpg" />
</li>
</ol>



<p>
Edit and delete follow a similar process with slightly different implementations in their ActionListeners.
</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/michael_bevels/dynamic_trees_in_jsf.html</link>
            <guid>http://www.nearinfinity.com/blogs/michael_bevels/dynamic_trees_in_jsf.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">General</category>
            
            
            <pubDate>Tue, 22 Apr 2008 14:15:23 -0500</pubDate>
        </item>
        
    </channel>
</rss>

