13 Replies Latest reply on Aug 6, 2010 12:32 PM by barrybuzz

    Custom function help for find/replace text with style

    barrybuzz

      Title

      Custom function help for find/replace text with style

      Post

      Hello,

      Running into trouble with my attempt at a custom function. The function needs to find in a given field this pattern:

      <b>some sort of text</b>

      and replace it with:

      some sort of text

      Here is what I have so far, but it's returning an error:

      Evaluate (

      Let (

      [

      startBold = Position ( TextAsEntered ;  "<b>" ; 1 ; 1 ) ;
      endBold = Position ( TextAsEntered ; "</b>" ;  startBold+5 ; 1 ) ;
      midBold = Middle ( TextAsEntered ; startBold + 5 ; endBold - startBold )

      ] ; //End variable definition and start calculation

      If ( startBold = 0; TextAsEntered;

            // Else
          Left ( TextAsEntered ; startBold - 1 )

          & TextStyleAdd (  midBold; Bold )

          & Right ( TextAsEntered; Length ( TextAsEntered ) - endBold - 5 )

         )  //End IF

        )  //End LET

      )  //End Evaluate

      Any input appreciated!

      BarryH

        • 1. Re: Custom function help for find/replace text with style
          philmodjunk

          What's the purpose of the Evaluate function here?

          Evaluate is usually used in expressions such that Evaluate ("5 + 5") returns 10. I don't follow why you need it here.

          + 5 looks like the wrong offset to me. <b> is only three characters so + 3 should return the start of the text to be styled as bold.

          Do you want this function to work on text like the following?

          This is a <b>big</b> problem in our <b>project</b>.

          You can do that by making your function recursive.

          I also suggest adding some error checking for cases where <b> doesn't have a matching </b>

          You also need to be aware of this issue as you work with your custom function:  Calculation fields using Custom Function do not re-evalute when custom function is updated as it can fool you into thinking your function is not working when it's just a case of your calculation field not reevaluating after you've modified the custom function definition.

          • 2. Re: Custom function help for find/replace text with style
            barrybuzz

            Thanks for the input.

            You're correct about the offset - should be three.

            • 3. Re: Custom function help for find/replace text with style
              barrybuzz

              Sorry, meant to post the rest of my response:

              You can do that by making your function recursive.

              Not sure how to make a function recursive?

              Error checking for a standalone <b> is a good idea. I think if I change:

              If ( startBold = 0; TextAsEntered;

              to

              If ( midBold = 0; TextAsEntered;

              That should take of most errors, yes?

              Evaluate is usually used in expressions such....I don't follow why you need it here.

              I tried it without the evaluate but got an error, so I thought the function might need to evaluate the whole contents of a given field before calculating the result. But I'm heardly an expert on this stuff. :-)

              The error returned is:

              • 4. Re: Custom function help for find/replace text with style
                barrybuzz

                Sorry did it again!

                Actually, now that I changed the function to this below, I'm getting no errors. I just have to check that's it's properly calculating results.

                Let (

                [

                startBold = Position ( WordList::u_explanation_t ;  "<b>" ; 1 ; 1 ) ;
                endBold = Position ( WordList::u_explanation_t ; "</b>" ;  startBold + 3 ; 1 ) ;
                midBold = Middle ( WordList::u_explanation_t ; startBold + 3 ; endBold - startBold )

                ] ; //End variable definition and start calculation

                If ( midBold = 0; WordList::u_explanation_t;

                      // Else
                    Left ( WordList::u_explanation_t ; startBold - 1 )

                    & TextStyleAdd (  midBold; Bold )

                    & Right ( WordList::u_explanation_t; Length ( WordList::u_explanation_t ) - endBold - 3 )

                   )  //End IF

                  )  //End LET

                • 5. Re: Custom function help for find/replace text with style
                  philmodjunk

                  Edit note: There are mistakes in this function. See the end of the thread for a corrected example.

                  Instead of testing midBold (which would be empty not 0 in cases of error, I believe, I'd just test to make sure startBold < EndBold.

                  Here's how I'd do it:

                  First, define a parameter, strText, for the function so that it doesn't refer directly to the field in your table

                  Let (

                  [

                  startBold = Position ( strText ;  "<b>" ; 1 ; 1 ) ;
                  endBold = Position ( strText ; "</b>" ;  startBold + 3 ; 1 ) ;
                  midBold = Middle ( strText ; startBold + 3 ; endBold - startBold )

                  ] ;

                  Case ( startBold = 0 ; strText ;
                             endBold > startBold ; strText ;
                             Left ( strText ; startBold - 1 ) & TextStyleAdd (  midBold; Bold )
                               & YourFunctionName ( Right ( strText ; Length ( strtext ) - endBold - 3 ) ) /* recursive call */
                           ) // end case
                  ) // end let

                            

                  • 6. Re: Custom function help for find/replace text with style
                    barrybuzz

                    Thanks for all of the suggestions, PhilModJunk! I'm making a lot of progress; just need to do some more capturing of errors & variations, then I think I'll have it.

                    The only outstanding questions that I have are these:

                    How to make a call recursive in FMP? With a Loop?

                    An maybe similarly, my current script is only capture the first occurrence of the <b>...</b>. How can I get it to find/replace ALL occurrences in a given field?

                    Thanks again!

                    Barry H

                    Here's the latest script:

                    Let (

                    [

                    startBold = Position ( TextAsEntered ;  "<b>" ; 1 ; 1 ) ;
                    endBold = Position ( TextAsEntered ; "</b>" ;  startBold + 3 ; 1 ) ;
                    midBold = Middle ( TextAsEntered ; startBold + 3 ; endBold - startBold - 3 )

                    ] ; //End variable definition and start calculation

                    If ( endBold > startBold ; TextAsEntered ;

                          // Else
                        Left ( TextAsEntered ; startBold - 1 )

                        & TextStyleAdd (  midBold; Bold )

                        & Right ( TextAsEntered; Length ( TextAsEntered ) - endBold )

                       )  //End IF

                      )  //End LET

                    • 7. Re: Custom function help for find/replace text with style
                      philmodjunk

                      How to make a call recursive in FMP? With a Loop?

                      An maybe similarly, my current script is only capture the first occurrence of the <b>...</b>. How can I get it to find/replace ALL occurrences in a given field?

                      Take another look at my last post. It is recursive (It calls itself). The recursive call loops through the text passed as a parameter to the function so that all text enclosed in <b>, </b> is styled in bold.

                      That's why this line:

                      Left ( strText ; startBold - 1 ) & TextStyleAdd (  midBold; Bold )
                                   & YourFunctionName ( Right ( strText ; Length ( strtext ) - endBold - 3 ) ) /* recursive call */

                      is written the way it is. You'd replace YourFunctionName with the name you've given your custom function so that it calls itself, passing the unprocessed portion of the text onward as a parameter.

                      Recursive function calls can have a kind of "smoke and mirrors" look to them that can be hard to follow until you get used to how they work.

                      • 8. Re: Custom function help for find/replace text with style
                        barrybuzz

                        Very cool! I'll try it out.

                        • 9. Re: Custom function help for find/replace text with style
                          barrybuzz

                          Hi again. It seems that I cannot get recursion to work. The calc returns a ? into the field. My custom function is called "StyleBold"

                          Removing the recursive part "StyleBold" (in front of "(Right(...") restores the the calculation, but of course I only get bolded text on the first instance of <b>...</b>.

                          Here's my current custom function (without recursion):

                          Let (

                                  [
                                   startBold = Position ( TextAsEntered ;  "<b>" ; 1 ; 1 ) ;
                                   endBold = Position ( TextAsEntered ; "</b>" ;  startBold + 3 ; 1 ) ;
                                   midBold = Middle ( TextAsEntered ; startBold + 3 ; endBold - startBold - 3 )
                                   ] ; //End variable definition and start calculation

                                 Case (
                                          endBold < startBold  ; TextAsEntered ;
                                          midBold = 0  or IsEmpty ( midBold ); TextAsEntered ;

                                          // Else
                                     Left ( TextAsEntered ; startBold - 1 ) & TextStyleAdd ( midBold; Bold )
                                         & ( Right ( TextAsEntered; Length ( TextAsEntered ) - endBold - 3) )

                                  )   //End CASE

                                ) //End LET

                          • 10. Re: Custom function help for find/replace text with style
                            philmodjunk

                            I'd rather have seen the function with recursion that didn't work.

                            I put my original post into a test file and after fixing a few details you've also fixed in your last post, it worked:

                            Here's my function, I named it BoldTaggedText and defined strText as the parameter passed to the function:

                            Let (

                            [
                            startBold = Position ( strText ;  "<b>" ; 1 ; 1 ) ;
                            endBold = Position ( strText ; "</b>" ;  1 ; 1 ) ;
                            midBold = Middle ( strText ; startBold + 3 ; endBold - startBold - 3 )
                            ] ;

                            Case ( startBold = 0 ; strText ;
                                       endBold < startBold ; strText ;
                                       Left ( strText ; startBold - 1 ) & TextStyleAdd (  midBold; Bold )
                                         & BoldTaggedText ( Right ( strText ; Length ( strtext ) - endBold - 3 ) ) /* recursive call */
                                     ) // end case
                            ) // end let

                            I tested it by defining a text field called "field" and then a calculation field named cStyledText with this expression as it's calculation:  BoldTaggedText ( TextField )

                            I kept the calculation unstored so that fixes made to the function definition would correctly update and selected "text" as the calculation field's return type.

                            With this function, 

                            This is a <b>test</b> of <b>this</b> function

                            became

                            This is a test of this function

                            • 11. Re: Custom function help for find/replace text with style
                              barrybuzz

                              I think I see what the difference might be. I'm using a text field sometextfield that auto-inserts a calculated value into the field. The calculated value is my custom function applied to text read from another text field.

                              So you're using a calc field and I'm using a text field with a calc that auto-enters  into the field.

                              I would think they almost would act the same except that you can't edit test in a calc field (which I'll need to be able to do).

                              When I make a dummy calc field somecalcfield and apply the CF with recursion, it properly calculates & reutrns accurately formatted text.

                              Ugh - rock, meet hard place. :)

                              So is there a way to "dump" the results of somecalcfield into an editable field?

                              Thanks again!

                              • 12. Re: Custom function help for find/replace text with style
                                philmodjunk

                                There's something else going on.

                                Auto entered cacluations will work the same way with this custom function as it does with calculation fields. Just make sure the "do not replace existing value..." option is not selected or changes to the referenced field won't trigger a change to the text field.

                                Also, changes to the custom function won't change what you see in the text field until you change the contents of this field in order to trigger a new call to the custom function. So always edit your field to remove, add or change some text after you modify your custom function.

                                • 13. Re: Custom function help for find/replace text with style
                                  barrybuzz

                                  Voila! What a great way to end the week. All of my relevant custom functions are recursive now and doing their job as I had hoped!

                                  PhilModJunk, you have been a tremdous help. Much appreciated.