Page 1 of 1

Populating Form Fields in word

PostPosted: Thu Apr 27, 2017 2:40 am
by irfanm
Hi,
I have a template which is protected and only thing i can do in that doc file is i can fill in the form texts and check boxes.
So i started researching about this and find a way to populate form text boxes using MailMerger, But every field reference is coming as FORMTEXT i am having around 50 text boxes, so when i write code for this every text box is updating with one value and content control is gone(means text box is not visible and only replaced text is visible).
And all these check boxes and text boxes are in tables, can we get table field references and modify form fields in it and add it back to mainDocumentPart?
Please help me out with this, i will attach my code to this post.


private static List<Object> performOnInstance(WordprocessingMLPackage input,
List<Object> contentList,
Map<DataFieldName, String> datamap,
FormTextFieldNames formTextFieldNames) throws Docx4JException {


Body shell = Context.getWmlObjectFactory().createBody();
shell.getContent().addAll(contentList);
Body shellClone = (Body)XmlUtils.deepCopy(shell);

ComplexFieldLocator fl = new ComplexFieldLocator();
new TraversalUtil(shellClone, fl);
log.info("Found " + fl.getStarts().size() + " fields ");



List<FieldRef> fieldRefs = new ArrayList<FieldRef>();
canonicaliseStarts(fl, fieldRefs);


for (FieldRef fr : fieldRefs) {

if ( fr.getFldName().equals("FORMTEXT") ) {

String instr = extractInstr(fr.getInstructions() );
String lang = extractLang(fr.getResultsSlot());
String datafieldName = getDatafieldNameFromInstr(instr);
String val = datamap.get( new DataFieldName(datafieldName));
String gFormat = null; // required only for FORMTEXT conversion

if (StringUtils.isBlank(val)) {
log.warn("Couldn't find value for key: '" + datafieldName + "'");
if (fieldFate.equals(OutputField.REMOVED)) {
// Remove the mergefield from the document
removeSimpleField(fr);


String text = getTextInsideContent(fr.getParent());

// If the parent still contains data, don't delete it
if (StringUtils.isBlank(text)) {
recursiveRemove(shellClone, fr.getParent());
}
}
} else {

// Now format the result
FldSimpleModel fsm = new FldSimpleModel();
try {
fsm.build(instr);
val = FormattingSwitchHelper.applyFormattingSwitch(input, fsm, val, lang);

gFormat = FormattingSwitchHelper.findFirstSwitchValue("\\*", fsm.getFldParameters(), true);
// Solely for potential use in OutputField.AS_FORMTEXT_REGULAR
// We are in fact applying all formatting switches above.

} catch (TransformerException e) {
log.warn("Can't format the field", e);
}

fr.setResult(val);
}

if (fieldFate.equals(OutputField.AS_FORMTEXT_REGULAR)) {

log.debug(gFormat);
// TODO if we're going to use gFormat, setup FSM irrespective of whether we can find key


// TODO: other format instructions
// if (gFormat!=null) {
// if (gFormat.equals("Upper")) {
// gFormat = "UPPERCASE";
// } else if (gFormat.equals("Lower")) {
// gFormat = "LOWERCASE";
// }
// }

// replace instrText
// eg MERGEFIELD CLIENT.ORGANIZATIONSTATE \* Upper \* MERGEFORMAT
// to FORMTEXT
// Do this first, so we can abort without affecting output
List<Object> instructions = fr.getInstructions();
if (instructions.size()!=1) {
log.error("TODO MERGEFIELD field contained complex instruction");
continue;
}
Object o = XmlUtils.unwrap(instructions.get(0));
if (o instanceof Text) {
((Text)o).setValue("FORMTEXT");
} else {
if(log.isErrorEnabled()) {
log.error("TODO: set FORMTEXT in" + o.getClass().getName());
log.error(XmlUtils.marshaltoString(instructions.get(0), true, true));
}
continue;
}

String fieldName = formTextFieldNames.generateName(datafieldName);
log.debug("Field name normalisation: " + datafieldName + " -> " + fieldName);
setFormFieldProperties(fr, fieldName, null);

// remove <w:highlight w:val="lightGray"/>, if present
// (corresponds in Word to clicking Legacy Forms > Form Field Shading)
// so that the result is not printed in grey
R resultR = fr.getResultsSlot();
if (resultR.getRPr()!=null
&& resultR.getRPr().getHighlight()!=null) {
resultR.getRPr().setHighlight(null);
}

} else if (!fieldFate.equals(OutputField.KEEP_MERGEFIELD)) {
// If doing an actual mail merge, the begin-separate run is removed, as is the end run
fr.getParent().getContent().remove(fr.getBeginRun());
fr.getParent().getContent().remove(fr.getEndRun());
}

// System.out.println("AFTER " +XmlUtils.marshaltoString(
// fr.getParent(), true, true));

}
}

return shellClone.getContent();

}

Re: Populating Form Fields in word

PostPosted: Mon May 01, 2017 6:49 pm
by jason
As a starting point, you need to understand fields in general (simple versus complex): http://webapp.docx4java.org/OnlineDemo/ ... L/XML.html

Then the difference in semantics between MERGEFIELD and FORMTEXT:

http://webapp.docx4java.org/OnlineDemo/ ... FIELD.html

http://webapp.docx4java.org/OnlineDemo/ ... MTEXT.html which says:

Description: Inserts a text box style form field which, when the editing of form fields is enabled using the documentProtection element (§2.15.1.28), can be typed into. An instance of this field shall be accompanied by a use of the ffData element (§2.16.17) which contains the form field's properties.


Glancing at your code, I couldn't see you accessing the ffData element.

I suggest you look at the XML in your docx to understand what you are working with. In any response to this message, please post relevant XML snippets (and use XML and Java tags as appropriate to format things, thanks).