Mail merge question- Aspose.Words for Java

Hello Support,

I have downloaded the trial version of Aspose Word (Java edition) and am having difficulty with the mail merge function.

Currently I have hundreds of Word documents that have mail merge tags; I would like to use Aspose Word to merge info from a database into these documents.

Unfortunately, most of the Word docs have pattern matches and the Aspose code seems to crash when it encounters a Word doc with a pattern.

Is there any fix for this issue?

Sorry I don’t understand what is a “pattern match” inside a document. To speed up resolution, please attach a sample document to this thread.

romank:

Sorry I don’t understand what is a “pattern match” inside a document. To speed up resolution, please attach a sample document to this thread.

I’ve attached a Word doc with mail merge patterns such as: ##########

Thanks,
Kaylon

Please specify what is exactly cause the document to crash. Are you just resaving the document with Aspose.Words. Or you are doing more complex manipulations. In the latter case please attach the code snippet.

Best regards,

BASICALLY, THE PATTERN IN THE WORD DOC “0####” GENERATES A MALFORMED PATTERN ERROR, i HAVE NO IDEA WHAT THIS MEANS.

HERE IS A CODE SNIPPET:

String[] names = { "TIME", "TITLE", "FIRST", "MI", "LAST", "SFX", "LINE_2", "ADDRESS", "STE", "CITY", "STATE", "ZIP", "Plus4", "POL_NO", "DEAR", "INITIAL_PAYMT", "LIM", "AGG", "DEDUCT", "PRIOR_ACTS", "PREM", "AD_FEE", "COST", "EFF_DATE", "ACCOUNT_EX", "AE_Email" };
Object[] obj = {time ," ", clientFName , clientMName , clientLName , clientSfx ,clientChkName ,
    cls(clientAddr.getAddress1()), cls(clientAddr.getAddress2()) ,cls(clientAddr.getCity()), cls(clientAddr.getState()), zip, Plus4,
    cls(polNum), cls(clientGnam.getFirstName()) + " " + cls(clientGnam.getLastName() ),"$" + StringUtilities.formatNumber( "###,###.##", Float.parseFloat(amt.getValue()) ) ,"$" + StringUtilities.formatNumber( "###,###.##", Float.parseFloat(lim.getValue()) ),"$" + StringUtilities.formatNumber( "###,###.##", Float.parseFloat(agg.getValue()) ), "$" + StringUtilities.formatNumber( "###,###.##", Float.parseFloat(deduct.getValue()) )
    ," ", "$" + StringUtilities.formatNumber( "###,###.##", Float.parseFloat(Float.toString(pol.getPremium())) ), "$" + StringUtilities.formatNumber( "###,###.##", Float.parseFloat( addFee.getValue()) ), "$" + StringUtilities.formatNumber( "###,###.##", Float.parseFloat( Float.toString(totalCost)) ), StringUtilities.formatDate( pol.getEffDate() ), cls(userGnam.getCheckName()), " " };

try
{
    doc = new Document(fileName);
    doc.getMailMerge().execute(names, obj);

}
catch (Exception e) { System.out.println(e + "- MergeUtil error -"); e.printStackTrace(); }

return doc;

HERE IS THE ERROR GENERATED:

/opt/jakarta-tomcat-4.1.31/webapps/AMS_WEB/files/R13.doc
java.lang.IllegalArgumentException: Malformed pattern "0####"- MergeUtil error -
java.lang.IllegalArgumentException: Malformed pattern "0####"
at java.text.DecimalFormat.applyPattern(DecimalFormat.java:2333)
at java.text.DecimalFormat.(DecimalFormat.java:407)
at com.aspose.words.gy.b(Unknown Source)
at com.aspose.words.gy.a(Unknown Source)
at com.aspose.words.gy.a(Unknown Source)
at com.aspose.words.gy.b(Unknown Source)
at com.aspose.words.gy.a(Unknown Source)
at com.aspose.words.MailMerge.execute(Unknown Source)
at com.aspose.words.MailMerge.execute(Unknown Source)
at com.core.beans.MergeUtil.execute(MergeUtil.java:101)
at com.core.servlets.DocMergeServlet.doPost(DocMergeServlet.java:94)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:716)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:809)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:200)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:146)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:209)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:144)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2358)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:133)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:118)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:594)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:116)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:594)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:127)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:152)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:534)
java.lang.ClassCastException
at com.aspose.words.fk.c(Unknown Source)
at com.aspose.words.fk.a(Unknown Source)
at com.aspose.words.Document.a(Unknown Source)
at com.aspose.words.Document.save(Unknown Source)
at com.aspose.words.Document.save(Unknown Source)
at com.core.servlets.DocMergeServlet.doPost(DocMergeServlet.java:99)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:716)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:809)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:200)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:146)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:209)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:144)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2358)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:133)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:118)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:594)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:116)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:594)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:127)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:152)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:534)

Hi, Kaylon,

Thanks for code snipped – you task is more clear now. There are two things: 1) Java vs. .Net core API differences and 2) how to solve you task.

First. For parsing mailmerge pattern strings (like “$###,###.00”, etc.) we using Sting.Format() in .Net and DecimalFormat.format() (for numbers and currencies) + DateFormat.format() (for date and time) – in java. These two approaches are generally equals in theirs main task – locale-independent formatting of numbers, currencies and dates, but have several differences:

  1. Java API can’t format phone and policy number patterns like: “(###) ###-##-##”, “##-##-##” and etc, because they are not numbers from java point of view (in your example this corresponds to “POL_NO” field).

  2. Java DecimalFormat doesn’t support leading zeroes – so it throws on your ZIP pattern “0####”.

  3. Java DecimalFormat doesn’t support third formatting group (for zeroes) so it ignored in java (first group – for positive number, second – for negative).

Second. Yours task.

For ZIP fields and alike (when you need to zero-padding constant width numbers) you can use String.format("%06d", zip) – this will produce 6-digit decimal number with zero-padding if needed.

For policy numbers and alike there is no simple API function in core java, imho (are you storing these things in decimal numbers, not in strings?).

For currencies you can use patterns like “$###,###.00” and don’t using your StringUtilities.

Best Regards,

Thank you for the information. But, I am not sure I understand your solution.

Are you suggesting that I remove the pattern from the Word document and use Java code to create the pattern?

If so, is there any way to keep the patterns in the Word doc?

The problem is that I have literally thousands of Word docs that already have these mail merge patterns coded in and I simply need a way merge the data without Aspose crashing when it encounters a pattern. It would take weeks to manually remove the patterns from the Word docs so I am looking for a possible Aspose solution.

Thanks.

Okay, if you can’t rework your patterns, there is another way:)

You can use MergeFieldEventHandler – this handler launched every time you launch mailmerge execute(), checks field name and merges field text “manually” irrespective to field pattern. So you can keep merge field pattern (but don’t use it).

There is a small example:

import java.text.DecimalFormat;
public class MailMergePatternTest implements MergeFieldEventHandler
{
    public void TestMailMergePattern() throws Exception
    {
        //used instead of "$" + StringUtilities.formatNumber( "###,###.##", Float.parseFloat(amt.getValue()) )
        DecimalFormat df = new DecimalFormat("$###,###.00");
        //open pattern doc
        Document doc = new Document("X:\Aspose\forum\R13_temp.doc");
        //merge field names and values
        String[] fieldNames = new String[] {"TITLE", "FIRST", "ZIP", "Plus4", "POL_NO", "ACCOUNT_EX" };
        Object[] values = new Object[] {"MY TITLE", "First name", 12345, 123, 12345678, df.format(12345.12)};
        //adding Merge Field Event Handler
        doc.getMailMerge().addMergeFieldEventHandler(this);
        //execute
        doc.getMailMerge().execute(fieldNames, values);
        //save
        doc.save("X:\Aspose\forum\R13_temp Out.doc");
    }

    //Merge Field Event Handler
    public void mergeField(Object sender, MergeFieldEventArgs e)
    {
        if ("ZIP".equals(e.getFieldName()))
        {
            e.setText(String.format("%06d", e.getFieldValue()));
        }
        else if ("Plus4".equals(e.getFieldName()))
        {
            e.setText(String.format("-%04d", e.getFieldValue()));
        }
        else if ("POL_NO".equals(e.getFieldName()))
        {
            Integer number = (Integer)e.getFieldValue();
            char[] c = number.toString().toCharArray();
            e.setText("LPL " + c[0] + " " + c[1] + c[2] + " " + c[3] + c[4] + " " + c[5] + c + "-" + c[7]);
        }
    }
}

Best Regards,

Thank you.

I have a new question/issue.

Attempts to merge text into a Word document that has Word text-box fields results in blank pages. Is Aspose capable of merging into Word text-box fields? If so, how?

Thanks again.

Are you asking about formfield textboxes in MS Word? They are not merged during mailmerge. You can set the formfield contents directly by using DocumentBuilder.InsertTextInput method. See the detailed description of formfield handling on
https://docs.aspose.com/words/net/working-with-form-fields/
Please let me know if you are asking about something else.
Best regards,

Hello,

I am referring to a basic Word text box, created when you click on "Insert " then “Text Box” in the MS Word control bar. Text within these textboxes do not seem to merge.

Thanks.

Hi,

Textboxes are not yet supported in Aspose.Words for Java. Please wait a couple of days until the new version is released. It will support shapes and hence textboxes.

Aspose.Words for Java 2.0.0 is released.
https://blog.aspose.com/2006/11/03/60502