PDA

View Full Version : Write a case rule with exceptions


traba5058
March 14th, 2012, 08:48 AM
I am a new Fusion Pro & Marcomm user and just getting started with Javascript.

I have 8 direct mail templates setup for a client. The client provides the list in all uppercase. This works great for the mailing panel but not so great when the name is used elsewhere in the piece.

Right now, the list has 1 name field (Full Name) and that is all their system can provide. That field contains First, Middle Initial, Last and Suffix.

I need to know how to change the following rule

var Var1 = "Full Name";
var CaseSelection = "propercase";


if(CaseSelection == "propercase")
return ToTitleCase(Field(Var1));

so it leaves I, II and III etc. suffixes uppercase.

Can anyone help?

Thanks!

Dan Korn
March 14th, 2012, 10:04 AM
Unfortunately, there's no computerized algorithm which can accurately calculate all the somewhat arbitrary capitalization rules for proper names. The ToTitleCase function also doesn't know how to properly capitalize names like McDonald or Werner von Braun, nor acronyms which are parts of names and addresses, such as directional notations like NW. For that matter, not every proper name conforms to the Western ideal of first, middle, last, and suffix.

So, using the rather simplistic ToTitleCase string processing function to cleanse or "fix" your data is perilous, as there are many, many exception cases where proper names do not conform to "title case" logic". Here's one of my rants about this from the old email list:
http://www.mail-archive.com/fusionpr.../msg01161.html (http://www.mail-archive.com/fusionpro@printplanet.com/msg01161.html)

You could theoretically apply the same kind of exception case logic as in that post, with a list of exceptions like I, II, III, etc., but I still don't recommend doing this, as you will undoubtedly find other kinds of names where forcing a particular mixed case style is simply not appropriate. This is why the USPS standardizes all mailing addresses to upper-case.

In short, there's really no reliable way to do programmatically restore the missing capitalization in the data, short of going back to the customer and getting the original data, before it was converted to all upper-case.

rpaterick
March 14th, 2012, 10:18 AM
Here is an example of how this code could work. You would have to add all scenarios to meet your customer's needs, as Dan states.


var Name = Field("Full Name");
Name = Name.replace("Sr","SR").replace("Jr","JR").replace("iii","III").replace("ii","II");
return Name;

traba5058
March 14th, 2012, 12:27 PM
Thanks so much for getting back to me! That code worked.

rpaterick
March 14th, 2012, 12:33 PM
Thanks so much for getting back to me! That code worked.

No problem. Just remember, if your record has "Iii" you will need to add that to the code to replace it with "III"(How your customer wants it) and other scenarios as well.

traba5058
March 14th, 2012, 12:41 PM
I actually manipulated it to read

var Name = Rule("ProperCase_FullName_Rule");
Name = Name.replace("Ii","II").replace("Iii","III").replace("IIi","III").replace("Iv","IV");
return Name;

One thing I noticed is that the PropoerCase rule changed III to Iii, but the rule above changed it to IIi. So, I had to add the "replace("IIi","III")" portion. Logically that didn't make sense to me. Do you have any thoughts on why I had to add that?

rpaterick
March 14th, 2012, 12:49 PM
I actually manipulated it to read

var Name = Rule("ProperCase_FullName_Rule");
Name = Name.replace("Ii","II").replace("Iii","III").replace("IIi","III").replace("Iv","IV");
return Name;

Do you have any thoughts on why I had to add that?

Unfortunately I'm no code expert but I see "replace" has a space after the "a." I know one thing with code, if it isn't spelled correctly, it won't work.

esmith
March 14th, 2012, 01:11 PM
I actually manipulated it to read

var Name = Rule("ProperCase_FullName_Rule");
Name = Name.replace("Ii","II").replace("Iii","III").replace("IIi","III").replace("Iv","IV");
return Name;

One thing I noticed is that the PropoerCase rule changed III to Iii, but the rule above changed it to IIi. So, I had to add the "replace("IIi","III")" portion. Logically that didn't make sense to me. Do you have any thoughts on why I had to add that?
That is because your first replace() checks for "Ii". The search will replace the first instance that matches that string whether it is "Ii" or "Iii". What you could do instead of adding another replace, would be to reverse the replace methods you already had. So replace("Iii", "III") would come before replace("Ii","II").

Keep in mind that if your field value were "John Iilian Ii", your result would be "John IIlian Ii" since the replace method only searches for the first match. There are ways around that, but they fall under JavaScript 301. ;)

Dan Korn
March 14th, 2012, 01:32 PM
Here is an example of how this code could work. You would have to add all scenarios to meet your customer's needs, as Dan states.


var Name = Field("Full Name");
Name = Name.replace("Sr","SR").replace("Jr","JR").replace("iii","III").replace("ii","II");
return Name;

Well, yes, although if you're going to do this, despite the caveats I offered, I think it's cleaner to create a simple array of exception-case strings and iterate through them, as in the example I cited (http://www.mail-archive.com/fusionpro@printplanet.com/msg01161.html), instead of chaining together a bunch of replace calls. Something like this:
var result = ToTitleCase(Field("Full Name"));
var Exceptions = [ "I", "II", "III", "IV" ];
for (var i in Exceptions)
{
var re = RegExp("\\b" + Exceptions[i] + "\\b", "gi");
result = result.replace(re, Exceptions[i]);
}
return result;This makes it a lot easier to add more exceptions to the list. Note also that my version only replaces entire words, while the simpler call to replace without the regular expression could result in output such as "IVerson".
I actually manipulated it to read

var Name = Rule("ProperCase_FullName_Rule");
Name = Name.replace("Ii","II").replace("Iii","III").replace("IIi","III").replace("Iv","IV");
return Name;

One thing I noticed is that the PropoerCase rule changed III to Iii, but the rule above changed it to IIi. So, I had to add the "replace("IIi","III")" portion. Logically that didn't make sense to me. Do you have any thoughts on why I had to add that?
Yes, well, that rule is very dependent on the order in which the replace calls are made, as it was doing case-sensitive searches. My solution does case-insensitive searches, as denoted by the "i" flag in the RegExp object. It also includes the "g" flag to replace all instances, not just the first, which probably doesn't matter much for a name with a single suffix, but it's technically more complete.

Dan Korn
March 14th, 2012, 01:44 PM
Unfortunately I'm no code expert but I see "replace" has a space after the "a." I know one thing with code, if it isn't spelled correctly, it won't work.
This was probably a result of pasting the code in directly without using and tags. If you're posting code to the forum, you can click the "Go Advanced" button, then select the code you pasted in and click the # button to add the appropriate tags, which will put the code in a special "Code" block as in my posts. You can also use the handy "Preview Post" button to make sure things look right before submitting. Okay, I'm taking my moderator hat off now. :)

traba5058
March 14th, 2012, 01:50 PM
Dan,

I created a new rule in Fusion Pro and pasted in your code

var result = ToTitleCase(Field("Full Name"););
var Exceptions = [ "I", "II", "III", "IV" ];
for (var i in Exceptions)
{
var re = RegExp("\\b" + Exceptions[i] + "\\b", "gi");
result = result.replace(re, Exceptions[i]);
}
return result;

Now I am getting an error when I validate it:

line 1:Syntax Error: missing ) after argument list.

Can you help me?

ThomasLewis
March 14th, 2012, 02:43 PM
There's an extra semicolon in the first line.
It should read:
var result = ToTitleCase(Field("Full Name"));

Dan Korn
March 14th, 2012, 04:01 PM
There's an extra semicolon in the first line.
It should read:
var result = ToTitleCase(Field("Full Name"));
Sorry about that. I edited my post to fix it. Here's the corrected version of the full rule:
var result = ToTitleCase(Field("Full Name"));
var Exceptions = [ "I", "II", "III", "IV" ];
for (var i in Exceptions)
{
var re = RegExp("\\b" + Exceptions[i] + "\\b", "gi");
result = result.replace(re, Exceptions[i]);
}
return result;

strido
June 19th, 2012, 12:34 PM
Sorry to resurrect the thread -

I'm having a bit of an issue here, using the typical ProperCase rule:


var Var1 = "AgencyName";
return ToTitleCase(Field(Var1));


Now, we have two clients that have capital letters in their name - ABC Corporation for instance. What's the syntax so it doesn't come out Abc Corporation? I tried the exceptions listed above but couldn't get that to work.

My client only has the two companies that this is affected by, so it's really not a matter of listing out every possible permutation. We'll be notified if any new ones arise, so it'll just be a matter of plugging them in.

Long story short, I'd like the ProperCase to continue, just not when the letters ABC are involved....

ThomasLewis
June 19th, 2012, 01:00 PM
Using an array the way Dan suggested is the easiest to manage when there are a lot of variables or when you know you'll be adding more in the future.

If you have a few static values you are dealing with or if you don't want to deal with arrays and loops you can use a simple if/else rule:

var Var1 = Field("AgencyName").toLowerCase();

if (Var1 == "abc corporation")
return "ABC Corporation";
else if (Var1 == "pti")
return "PTI";
else
return ToTitleCase(Var1);

In this case I am pre-converting the Field value to lowercase then checking just to be safe as it has to be an exact match.

strido
June 19th, 2012, 02:30 PM
That didn't seem to want to work....

http://i136.photobucket.com/albums/q195/strido527/Capture-4.jpg

I'm still getting the first letter Upper Case and the 2nd Lower. It should say "MW" both upper....

ThomasLewis
June 19th, 2012, 03:10 PM
As stated, it has to be an exact match to the entire string, the only exception being that it's all going to be in lowercase to get around any inconsistencies with case.

if (Var1 == "mw financial")
return "MW Financial";

mw Financial, Mw financial, MW Financial, would all work because they are forced to lowercase before being compared to == "mw financial".

The misspelled "mw finacail" would not work. You would have to put in another else if to handle misspellings. This is where Dan's suggestion of using an array and loop would be preferable as you could add in lots of variants easily.

Alternatively you could do something like this:

if (Var1.substring(0,3) == "abc")
return "ABC Corporation";
else if (Var1.substring(0,2) == "mw")
return "MW Financial";

This just checks for a match of the first few characters and doesn't worry about anything after. So the misspelling later in the word would still be a match. The only problem with this would be if you had a few agencies that started with the same letters.

strido
June 20th, 2012, 07:38 AM
That'll do! Thanks!