20 Replies Latest reply on Jul 10, 2009 3:19 AM by mcolmenero

    English numbers to French?

    DrSchoen Level 1
      I'm working on a massive English annual report right now. When it comes to the French the client will be providing a translation of the text, but not the numbers that appear in the financial statements; I am to take the numbers from the English. Rather than manually change all the formatting of the English numbers I'm wondering how to do a search and replace. For example, in English the number 12,450.67 needs to become 12 450,67 in French (comma becomes a space, period becomes a comma). Also things like 45.00% need to become 45,00% (period becomes a comma).
        • 1. Re: English numbers to French?
          Level 1
          you don't need scripting for that :)

          which version of ID you have ?

          robin

          --
          www.adobescripts.com
          • 2. Re: English numbers to French?
            DrSchoen Level 1
            The annual report is composed in InDesign CS3. Thank you.
            • 3. Re: English numbers to French?
              [Jongware] Most Valuable Participant
              (?) My previous answer is gone in digital space. (Can anyone hear me scream?)

              GREP to the rescue. Search for

              >,(\d\d\d)

              and replace with

              >~S$1

              This replaces the commas in "12,345.67" with a fixed space. Next, only periods inbetween two digits should be replaced with a comma, right? Search for

              >(\d)\.(\d)

              and replace with

              >$1,$2

              The period in the Search expression needs a backslash escape because it's a special character in GREP searches ("any character").

              If you need to run this on multiple documents, store each search-and-replace sequence under a logical name, and search this forum for the little script to chain them automatically.
              • 4. Re: English numbers to French?
                DrSchoen Level 1
                Brilliant! Many thanks. Worked like a charm and save me a lot of time making the changes manually.
                • 5. Re: English numbers to French?
                  L. Tournier Level 3
                  It will be better if you use a thin space : ~<$1
                  • 6. Re: English numbers to French?
                    mcolmenero Level 1

                    Hi,

                    I am a new user programming indesign script.

                    I have the same problem, but i don´t know wich is the code that change 12,345.67 to 12 345,67.

                    Could you help me please?

                    Thanks.

                    Best regards.

                    Miguel

                    • 7. Re: English numbers to French?
                      [Jongware] Most Valuable Participant

                      The idea from post #2 on is that a script is not necessary (at least, from CS3 onwards).

                       

                      However, if you need to script this, it's a simple case:

                       

                      app.findGrepPreferences = NothingEnum.nothing;
                      app.findGrepPreferences.findWhat = "xx";
                      app.changeGrepPreferences = NothingEnum.nothing;

                      app.changeGrepPreferences.changeTo = "yy";

                      app.activeDocument.changeGrep();

                       

                      Put the search expression into "xx" and the replace expression into "yy", and that's it.

                      You have to double every backslash, because the backslash in itself is a special character in Javascript strings as well.

                      • 8. Re: English numbers to French?
                        mcolmenero Level 1

                        Hi Jogware,

                        I put like this

                         

                         

                        app.findGrepPreferences = NothingEnum.nothing;
                        app.findGrepPreferences.findWhat = " ,(\d\d\d)"; //like find 1,000.52
                        app.changeGrepPreferences = NothingEnum.nothing;

                        app.changeGrepPreferences.changeTo = $1; I want to take 000

                        app.activeDocument.changeGrep();

                         

                        And it give me this error " $1 is not define".

                        I need make before to can use $1,$2.. something?

                         

                        I think that   $0= complete string

                                            $1=first part of string

                                            $2 =second part of string....

                         

                        And other question, how i can take a part of string?

                        Thanks

                        Best regard

                        • 9. Re: English numbers to French?
                          [Jongware] Most Valuable Participant

                          You have the general idea, but I see 2 immediate errors

                           

                          First off, the backslash is a special character in Javascript -- '\n', for instance, is a newline, and javascript sees the actual code 0x0a. So any backslashes that should be fed into InDesign as such should be doubled:

                           

                          app.findGrepPreferences.findWhat = ",(\\d\\d\\d)";

                           

                          (There should also not be a space immediately after the first quote.)

                           

                          Second, the changeTo expression is also a string, so it should be inbetween quotes:

                           

                          app.changeGrepPreferences.changeTo = "~S$1";

                           

                          and you forgot the "~S" -- the hard space.

                           

                          To pick apart a Javascript string, you can use string.substr(start, length). This, and further string manipulations, can be found online in any good JS reference.

                          • 10. Re: English numbers to French?
                            mcolmenero Level 1

                            Hi Jogware,

                            It`s go on that you say me. but now i have other problem. I want to make this operation product to 1.02 but say me a error, this is the code:

                             

                             

                            app.findGrepPreferences.findWhat ="(\\€)(\\d),(\\d\\d\\d)(.\\d*)"

                            app.changeGrepPreferences = NothingEnum.nothing;
                            myPercentage = (2 + 100)*.01;

                            var cadena=parseFloat("~S$2~S$3~S$4") *myPercentage;
                            app.changeGrepPreferences.changeTo = cadena;

                            app.activeDocument.changeGrep()

                             

                            The error is "invalid value for set property changeTo. Expected string or Nothing, Enum enumerator, but received Nan"

                             

                            I think that the problem is because if the Grep find ex. €1,000.10 and the result for parseFloat is "~S$2~S$3~S$4" =1 000 ,10, Perhaps the problem is white space?

                            Could you help me please? Then i want to return the same format. 1,020.10

                            Thanks

                            Best regards

                            Miguel

                            • 11. Re: English numbers to French?
                              [Jongware] Most Valuable Participant

                              You can do a lot with GREP, but it can't do the calculations for you. So you cannot use 'changeGrep'.

                              You are also putting a lot of faith in parseFloat!

                               

                              This function determines if the first character in the specified string is a number. If it is, it parses the string until it reaches the end of the number, and returns the number as a number, not as a string. (http://www.w3schools.com/jsref/jsref_parseFloat.asp)

                               

                              So it will return a value of "99.0" when you feed it "99 bottles of beer", but it cannot work with GREP syntax strings.

                               

                              The usual trick is to search all instances with findGrep -- this returns *all* found items at once in an array --, then change them one by one using "regular" javascript. The found array is a list of pointers right into your InDesign document, so if you change the contents of one found item, you might invalidate the others (particularly if you insert or delete characters). So, an additional trick is needed: if you are going to change the contents, do so from last to first.

                               

                              The following is untested, but it might be something to build on. I'll walk you through the steps one by one.

                              First, get an array of found items:

                               

                              app.findGrepPreferences.findWhat =€\\d,\\d\\d\\d.\\d*

                              foundItems = app.activeDocument.findGrep();

                               

                              There is no need for parentheses in the Find expression, because we are not using changeGrep. (There is also no need to put a backslash before the Euro sign -- where did that come from?) Now foundItems contain an array of pointers to all found occurrences -- you can check how many by adding

                               

                              alert ("Hey! We found "+foundItems.length+" items!");

                               

                              (Please do this at least once to check if the find expression is correct! If it is not, you'll keep wondering why the rest doesn't work!)

                              Each of the foundItems look like "€1,234.56" in memory.You cannot calculate with that, so we have to snip off the Euro sign and remove the comma. The period can stay in -- it's the decimal fraction separation in javascript as well.

                              We know the very first character always is a euro sign, so we can cut it off using the regular Javascript substr function. We have to do a few manipulations on the foundItems text, so it's a bad idea to change "foundItems" directly (remember, it only points to the location in your InDesign document -- any change will be reflected directly in the document itself). Assigning the contents to a variable "copies" the text into the variable.

                               

                              var result = foundItems[0].contents; // copy text

                              result = result.substr(1);

                               

                              The substr function expects an offset and length, but if you omit the length, it'll use the rest of the string. Now the variable result will hold "1,234.56". Let's remove the comma.

                              We don't know for sure where the comma is in the text, but we could use indexOf(",") to get the exact location, cut up the string into two parts and glue them together without the comma. Using the javascript replace function is a bit easier -- it does exactly what you'd expect :-)

                               

                              result = result.replace (",", ""); // replace comma with nothing

                               

                              Now result contains "1234.56", and this, finally, can be used to calculate with:

                               

                              result = parseFloat(result)*1.02;

                               

                              After this, result wil be "1259.2512". Way too much digits after the period, so we have to trick JS into using only two:

                               

                              result = Math.round(result*100)/100;

                               

                              After multiplying with 100 (getting "125925.12", the round function rounds off the number to "125925", and dividing again by 100 yields "1259.25". Exactly what we want! Let's insert the comma again -- this time using GREP inside Javascript. GREP was part of JS even before CS3.

                              First thing to note is that "result" is now a numeric value (because we did math on it), and we have to force it back to a string.

                               

                              result = String(result);

                              result = result.replace(/(\d\d\d\.)/, ",$1");

                               

                              (Notice the different syntax in the replace function, telling Javascript it's a GREP expression.) Stick a euro sign in front:

                               

                              result = "€"+result;

                               

                              and we're done! Well, apart from putting it back into the document, that is.

                              If you have been paying attention , you'll remember we have to work from last foundItem to first, so let's create a loop in the correct direction:

                               

                              for (var i=foundItems.length-1; i >=0; i--)

                              {

                                var result = foundItems[i].contents; // which is what I started with above

                                .. all calculations on 'result' come here ..

                                foundItems[i].contents = result; // put the result back into the document

                              }

                               

                              I think it should work. Don't you?

                              • 12. Re: English numbers to French?
                                [Jongware] Most Valuable Participant

                                Drat. I know I said

                                 

                                I think it should work. Don't you?

                                 

                                but with some further thought .. I think the decimal rounding could go wrong.

                                 

                                What if there is only one digit after the period, or (also possible) none at all?

                                Don't use the round trick I mentioned before; instead, use

                                 

                                result = Math.round(result*100);

                                 

                                That will always give you two decimals worth of precision, even if they are both zero. Suppose 'result' is '1.00'. The former line would give you round(1.00*100) = 100, then round(1.00*100)/100 = 1 -- no decimal point, no precision left. We can insert the period where needed in the string representation, because then the extra zeros at the end will not be discarded:

                                 

                                result = String(result);

                                result = result.replace(/(\d\d)$/, ".$1"); // plug in period at correct position

                                result = result.replace(/(\d\d\d\.)/, ",$1"); // from here on unchanged

                                • 13. Re: English numbers to French?
                                  mcolmenero Level 1

                                  Hi jogware,

                                  It's perfect thaks.

                                  Now I change app.findGrepPreferences.findWhat ="€\\d.\\d\\d\\d,\\d*", because i have diferent format to looking for example:

                                  €1.000,10-->"€\\d.\\d\\d\\d,\\d*"

                                  €12.000,10-->""€\\d\\d.\\d\\d\\d,\\d*"

                                  €123.000,10-->"€\\d\\d\\d.\\d\\d\\d,\\d*"

                                  Exist any formula to looking for anything? because if i put "€\\d*.\\d\\d\\d,\\d*" found this 1000,10 and I don´t want to find this.

                                  Or I need to make the three format?.

                                  Thanks

                                  Your are genial.

                                  Best regards

                                  • 14. Re: English numbers to French?
                                    [Jongware] Most Valuable Participant

                                    Okay, that may make a few things more complicated

                                     

                                    if i put "€\\d*.\\d\\d\\d,\\d*" found this 1000,10

                                     

                                    Yeah, that's because the first decimal \\d* did not find anything, but the next character '.' did -- the single period is a match-any wildcard, so it picked up the first digit after all. To search for a literal period, you should have entered "\\." (backslash -- doubled -- period). (But I'm wondering why it found something without the euro sign...)

                                     

                                    To search for any number of thousands before the comma, try something like

                                     

                                    €(\d?\d?\d,)*\d?\d?\d\.\d\d

                                     

                                    from within InDesign. See if that finds your numbers, and if so, double the backslashes and put it into the script.

                                    The question marks after the \d's mean "zero or one", the asterisk after the first parentheses mean "the entire preceding group zero or more often". If I'm correct, it will find anything like "€0.01", "€1,000.99", and "€1,999,999,999.95" (but also "€1,2,3.33" -- I hope there are no malformed numbers in your text!).

                                    The problem lies in how to convert this to a real fractional number, so you can do your calculations on it. I *think* all you need to change in your script is removing each and every comma with

                                     

                                    result = result.replace(/,/g, "");

                                     

                                    instead of the line that removes a single comma. The reason for this is the "replace" function only does its replacement once, for the first occurrence. Rewriting it as a GREP expression means you can use the 'g' modifier, which stands for "global".

                                     

                                    [Jongware]

                                     

                                    [Edit] Oops -- I see I reverted commas and periods *again*. Well, seems you made the right changes. Just remember to search for "\\." if you need a period. The replace line should (probably) read 'result = result.replace (/\./g, "")'

                                    • 15. Re: English numbers to French?
                                      mcolmenero Level 1

                                      Hi Jongware,

                                      I put your format, but change other format finally I have written:

                                      app.findGrepPreferences.findWhat ="€\\d?\\,?\\d?\\d?\\d,\\d\\d\\d.\\d*"; with this format doesn´t mix the diferent format, but I know only find number €1,123,000.10 or 123,000.10 or 1,000.10.

                                      My problem now is put again the same format. With next code:

                                          result = result.replace(/(\d\d\d\.)/, ",$1"); // from here on unchanged

                                      It put good format 123,000.10 or 1,000.10, but no 1,123,000.10. The last write 1123,000.10.

                                      What do I need? I don´t understand right  result = result.replace(/(\d\d\d\.)/, ",$1").

                                      Could you explain me.

                                      Thanks

                                      • 16. Re: English numbers to French?
                                        [Jongware] Most Valuable Participant

                                        The default "replace" function only replaces once ... (the first occurrence it finds). I fell for that as well first time I needed it.

                                        If you add 'g' after the GREP search command, it becomes a 'global' replace, changing all occurrences:

                                         

                                        result = result.replace(/(\d\d\d\.)/g, ",$1");

                                        • 17. Re: English numbers to French?
                                          mcolmenero Level 1

                                          Hi Jongware,

                                          Thanks. Finally I finish the script to update price. This week I will watch the script to my boss.

                                          Your welcome.

                                          Miguel

                                          • 18. Re: English numbers to French?
                                            mcolmenero Level 1

                                            Hi Jongware,

                                            One question more.

                                            How I can count how many decimal have in a number?

                                            I have this problem, if the number is 1440,40, the script keep off the last 0 and write 1440,4.

                                            Thanks

                                            best regards

                                            Miguel

                                            • 19. Re: English numbers to French?
                                              [Jongware] Most Valuable Participant

                                              Yes, I thought of that myself after posting my first solution. Do not divide by 100 and round, but keep your number "times 100". Do your calculations, and only plug in the comma at the correct position right before inserting the text back into your document. No maths needed, just a string operation. I used yet another GREP replace for that -- it's somewhere higher up in this post thread (it's the one starting with "Drat.").

                                              • 20. Re: English numbers to French?
                                                mcolmenero Level 1

                                                Hi,

                                                I have resolve like this:

                                                    var myIndex = result.indexOf(',');
                                                            var partes = result.substr(myIndex+1,2);
                                                            var b=partes.length;
                                                            if (b<2)
                                                            {
                                                                if (b>0)
                                                                {
                                                                    result=result+ "0";
                                                                }

                                                Before you resolved if we hadn´t any decimal.

                                                thanks

                                                Best Regards