mardi 25 avril 2017

How to set Checkbox value in Word document using OpenXML

I have been trying to get this to work for days now and am posting here as a last resort.

Background - I am creating a web application that allows a user to enter data into a web page and this data get translated into a Microsoft Word document using placeholders. This Word document is a template that gets populated with data and saved to the users computer.

Features Solved - I have managed to populate all of the required text fields with user data. This is no issue at all. I have created a search and replace method that does all of this for me so I am not asking for assistance in relation to this.

Issues - Included in the data that the user enters in on the web page are several boolean values. These boolean values will be used to either check or un-check certain Checkboxes in the Word document. Each Checkbox in the Word document has a Bookmark that needs to be used to locate it. I have tried several ways to search through the entire xml of the Word document and alter the value assigned to that specific Checkbox element.

Sample xml extracted from Word template

<w:document>
<w:body>        
    <w:tbl>         
        <w:tr>          
            <w:tc>          
                <w:p w:rsidR="007D2E4C" w:rsidRPr="00233E81" w:rsidRDefault="007D2E4C" w:rsidP="007D2E4C">
                    <w:r>   RUN
                        <w:fldChar w:fldCharType="begin">
                            <w:ffData>
                                <w:name w:val="cbxmeal0"/>
                                <w:enabled/>
                                <w:calcOnExit w:val="0"/>
                                <w:checkBox>
                                    <w:sizeAuto/>
                                    <w:default w:val="0"/>
                                </w:checkBox>
                            </w:ffData>
                        </w:fldChar>
                    </w:r>
                    <w:bookmarkStart w:id="10" w:name="cbxmeal0"/>
                    <w:r>
                        <w:rPr>
                            <w:sz w:val="20"/>
                        </w:rPr>
                        <w:instrText xml:space="preserve"> FORMCHECKBOX </w:instrText>
                    </w:r>
                    <w:r w:rsidR="00B128CE">
                        <w:rPr>
                            <w:sz w:val="20"/>
                        </w:rPr>
                    </w:r>
                    <w:r w:rsidR="00B128CE">
                        <w:rPr>
                            <w:sz w:val="20"/>
                        </w:rPr>
                        <w:fldChar w:fldCharType="separate"/>
                    </w:r>
                    <w:r>
                        <w:rPr>
                            <w:sz w:val="20"/>
                        </w:rPr>
                        <w:fldChar w:fldCharType="end"/>
                    </w:r>
                    <w:bookmarkEnd w:id="10"/>
                </w:p>
            </w:tc>
        </w:tr>
    </w:tbl>
</w:body>

The above xml text is a super simplified version but the structure is exactly the same. A simpler version of the structure is here Document > Body > Table > Table_Row > Table_Cell > Paragraph > Run > Field_Char > Form_Field_Data > Checkbox

Below is my extremely ugly way of iterating through the xml text in an attempt to locate the bookmark and checkbox. Note: I was only planning on getting it working and then I will optimise later.

            foreach (var table in document.MainDocumentPart.Document.Body.ChildElements.Where(t => t is DocumentFormat.OpenXml.Wordprocessing.Table))
        {
            foreach (var row in table.ChildElements.Where(r => r is DocumentFormat.OpenXml.Wordprocessing.TableRow))
            {
                foreach (var cell in row.ChildElements.Where(c => c is DocumentFormat.OpenXml.Wordprocessing.TableCell))
                {
                    foreach (var paragraph in cell.ChildElements.Where(p => p is DocumentFormat.OpenXml.Wordprocessing.Paragraph))
                    {
                        foreach (var run in paragraph.ChildElements.Where(r => r is DocumentFormat.OpenXml.Wordprocessing.Run))
                        {
                            foreach (var fieldChar in run.ChildElements.Where(fc => fc is DocumentFormat.OpenXml.Wordprocessing.FieldChar))
                            {
                                foreach (var formFieldData in fieldChar.ChildElements)
                                {
                                    foreach (var child in formFieldData.ChildElements)
                                    {
                                        //Check bookmark name
                                        //If bookmark name matches, 
                                        //Set checkbox value to true
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

If anyone can provide any assistance, whether it's a website address or actual code, that would be extremely helpful as I am losing faith in this quest! Also, forgive my LINQ usage as I have very little experience using it!




Aucun commentaire:

Enregistrer un commentaire