Format certain words in the merge field value differently?

Hello -

I am using Aspose.Words to do a mail merge and I have setup a MergeFieldEventHandler to use Aspose.Spell to spell check the value of the merge field. In the MergeFieldEventHandler, two things happen:

1. Highlight the merge field text to yellow.

2. If the value is spelled wrong, underline it with the color red.

This works great if the merge text is only one word, but if it is a sentence, then the whole sentence is underlined if one word is spelled wrong. I was wondering if it is possible to format certain words in the merge field value differently? For example:

This is a DailyLiving goal. instead of the whole sentence getting underlined. Let me know if you want to see my MergeFieldEventHandler code.

Thanks,

Shawn

When the field is merged the data text is appended as one run.

To apply separate formatting for words you need to break the run, containing sentence, into separate runs with one word (or delimiter, or space) per run. To achieve this you should:

  1. Get a hold of run, containing sentence.
  2. Get text of this run.
  3. Break the sentence text into parts: words, delimiters and whitespaces.
  4. Create a collection of runs, each containing one part of a sentence.
  5. Add these runs, one by one, after run, containing sentence.
  6. Remove run, containing sentence, from the parent paragraph.

After that you will be able to apply different formatting for each word in the sentence.

Thanks for the reply - I don't know if I really understand what to do. I have attached my code to show what I am currently doing in the MergeEventHandler, can you show me what I need to change to do what you are explaining?

Thanks,

Shawn

Ok, here is what you need to do. In HandleMergeField replace the current else block with the folllowing code:

KeyValuePair<string, bool>[] phrases = _spellChecker.SplitPhraseOnSpellCheck((string)e.FieldValue);

DocumentBuilder builder = new DocumentBuilder(e.Document);

// Move builder to merge field. The merge field itself is removed after movement is done.

builder.MoveToMergeField(e.FieldName);

// Save default formatting for merged text.

Underline defaultUnderline = builder.Font.Underline;

for (int i = phrases.Length - 1; i >= 0; i--)

{

KeyValuePair<string, bool> phrase = phrases[i];

bool phraseCorrect = phrase.Value;

string phraseText = phrase.Key;

// Apply highlighting formatting if necessary.

if (!phraseCorrect)

builder.Font.Underline = Underline.Wavy;

builder.Write(phraseText);

// Restore default formatting.

builder.Font.Underline = defaultUnderline;

}

Please note that to make the above code work correctly, SplitPhraseOnSpellCheck method should preserve all text including spaces and punctuation marks. Please make sure that it does because, I am actually inserting the parts produced by this method one by one in the above code. If you omit something when parsing - it will be missing from the document text too.

Here, I can suggest the following method to split the text into parts (words, spaces and punctuation marks):

string text = e.FieldValue.ToString();

ArrayList textParts = new ArrayList();

foreach(Match match in textParser.Matches(text))

{

textParts.Add(match.Value);

}

It breaks text into words, spaces and punctuatuion marks and uses the following regular expression for parsing:

private static Regex textParser = new Regex(@"\w+|\W", RegexOptions.Compiled);

I think you will be better off using this method as you would be able to underline separate words for incorrect spelling, just as MS Word does it.

Hope this helps,

Thanks - this works great except now I loose the formatting of the Merge Field that already present in the Template. I described this in an earlier post:

Anyway to keep the original formatting?

Thanks,

Shawn

Are you sure? The font formatting of DocumentBuilder is taken from merge field end. So if you merge field value, like «Field1», has correct formatting applied then field end should also be formatted that way and merge text will have the formatting also set like this.

However, if you still think that you have this problem, then please attach some sample documents as before and after mail merge. I will research the matter further.

Best regards,

Here is an example template before and after the mail merge along with sample input data.

The merge field at the top of the template <> has a format applied to it so it should print as April 14, 2007 but instead it comes out as 04/14/2007 after using the above code. In my other post () we got it traced down to the

// Move builder to merge field. The merge field itself is removed after movement is done.

builder.MoveToMergeField(e.FieldName);

Once I commented this line out, it would format the date properly. This might only be a problem with Date formatting.

Thanks for your help.

Shawn

Ok, I see. Yes, when you merge data manually using MoveToMergeField, the merge formatting implemented in Aspose.Words engine is skipped. You need to apply it in your code before any other processing will take place:

...
if (e.FieldValue == null) return;
string text = ApplyMergeFormat(e);
KeyValuePair[] phrases = _spellChecker.SplitPhraseOnSpellCheck(text);
...

And here is a code to apply merge formatting taken from merge field switches:

///
/// Apply merge field formatting to merged data.
///

private string ApplyMergeFormat(MergeFieldEventArgs e)
{
string fieldCode = e.Field.GetFieldCode();
object fieldValue = e.FieldValue;

Match match = regexMergeSwitchFinder.Match(fieldCode);

string formattedValue = e.FieldValue.ToString();

if (match.Success)
{
string numSwitch = match.Groups["numswitch"].Value;

if (numSwitch != "")
{
formattedValue = Convert.ToDouble(fieldValue).ToString(numSwitch);
}

string dateSwitch = match.Groups["dateswitch"].Value;

if (dateSwitch != "")
{
dateSwitch = dateSwitch.Replace("am/pm", "tt");
formattedValue = Convert.ToDateTime(fieldValue).ToString(dateSwitch);
}
}

return formattedValue;
}

private static Regex regexMergeSwitchFinder = new Regex(@"\#\s*""(?[^""]*)""|\@\s*""(?[^""]*)""", RegexOptions.Compiled);

Hope this helps,

It works perfectly - you guys are awesome!

Thanks,

Shawn