Jonas Löfvenmark Posted May 15, 2011 Posted May 15, 2011 I have a textfield containing really weired formated text, like: [T] Hello I am a header This is a [ci]paragraph[/c] with some [cb]fomated[/c] words! I am list item I am list item to. [TS] A smaller header And here there is some more text. That I need to get into a HTML accepable format like: <H3>Hello I am a header</H3> <p>This is a <i>paragraph</i> with some <b>fomated</b> words!</p> <ul><li>I am list item</li> <li>I am list item to.</li></ul> <h4>A smaller header</h4> <p>And here there is some more text.</p> My idea was to split everything up in paragraphs, check if the paragraph has a custom tag - if not just put p-tags around it, or if it has a tag - put the corresponding h-tag or what ever I set up to match the custom tag. But THEN there are lists so I need to check the previous and following paragraph if they too have the same tag - so I know weather to open/close the list or not. AAARRGGHH, my head is spinning.... and I can not really figure out how to loop the paragraphs to begin with. Any smallest of help or insight is much appreciated, thank you!
comment Posted May 15, 2011 Posted May 15, 2011 You posted this in Calculations, but I think you should be doing this in a script (that is assuming you should be doing this in Filemaker at all). I can not really figure out how to loop the paragraphs to begin with. Try something like: Set Variable [ $text ; YourTable::Textfield ] Loop Set Variable [ $i ; $i + 1 ] Exit Loop If [ $i > ValueCount ( $text ) ] Set Variable [ $para ; GetValue ( $text ; $i ) ] ... End Loop
Jonas Löfvenmark Posted May 15, 2011 Author Posted May 15, 2011 You posted this in Calculations, but I think you should be doing this in a script (that is assuming you should be doing this in Filemaker at all). My intentions was for this to be a calculated field - sorry if I am in the wrong place - as there is a lot of data and it is constantly changing, and handling needs to be done by others too.
comment Posted May 15, 2011 Posted May 15, 2011 I am not saying it cannot be done by a calculation. However, this requires recursive processing, hence a custom function. A looping script is easier to write and debug. Perhaps once you have the script working, you can adapt the logic to a custom function - or just attach a script trigger to the field. there is a lot of data and it is constantly changing You mean you still have people supplying you with data in this format? What is the source here? Perhaps there already is a conversion tool available.
Jonas Löfvenmark Posted May 17, 2011 Author Posted May 17, 2011 You mean you still have people supplying you with data in this format? What is the source here? Perhaps there already is a conversion tool available. No tool in existance, I am afraid. I remember looking at this some time back and came up with a some field calculation involving evaluate and let functions, using variables and patterncount to loop through each paragraph of a text. It was not very complex code, but I can not for the life of me seem to recall the basic syntax. I came across the following code in searching the forums which sort of sparked my memory, but this one is of course letter by letter, and I need it to be paragraph by paragraph (also I do not know what the "Invert" function should be, so I can not run the example...) Let([ $counter = $counter + 1 ; stop = Left ( text ; 1 ) ]; Case( $counter < Length ( text ) ; Middle ( text ; Length ( text ) + 1 - $counter ; 1 ) & Invert ( text ); Let ( $counter = "" ; stop ) ) ) Any input on how to adopt the code above is very much appreciated!
Vaughan Posted May 17, 2011 Posted May 17, 2011 There is no Invert function in FMP. It must be a custom function of some sort, but I have no idea what it could be. There is no function by that name on Brian Dunning's site.
comment Posted May 17, 2011 Posted May 17, 2011 The code you quote *is* a custom recursive function - most likely named Invert(). To loop on paragraphs using a custom function, you could do something like: Let ( [ para = GetValue ( text ; 1 ) ; paraCount = ValueCount ( text ) ; processedPara = <do some processing here> ]; processedPara & Case ( paraCount > 1 ; ¶ & MyCustomFunction ( RighValues ( text ; paraCount - 1 ) ) ) )
Raybaudi Posted May 17, 2011 Posted May 17, 2011 also I do not know what the "Invert" function should be... The Invert function is THE custom function of which you showed the code.
Jonas Löfvenmark Posted May 22, 2011 Author Posted May 22, 2011 The code you quote *is* a custom recursive function - most likely named Invert(). Thank you for explainig, my minds is still wondering a bit though: a custom function needs FM Pro Advanced, right? Where as a calculated field is regular FM Pro? I need it to be FM Pro.... I have come up with something like this - just to irelate the paragraphs, but it is not right: Let( [$i = $i + 1 ; count=PatternCount(Text;¶)]; Middle( Text ; Position(Text;¶;0;$i) ; Position(Text;¶;0;$i+1) ) & If ( $i < count ; ¶ & FormatedText ; Let( $i = "" ; "" ) ) ) Text is the source textfield and FormatedText is the calculation field containing the code. When doing this in the past, I remeber the most efficient way to go was accually backwards - starting with the last paragraph and moving to the first - but I can not seem to figure that out now to set that up. Any input? Thanks in advance!
comment Posted May 22, 2011 Posted May 22, 2011 a custom function needs FM Pro Advanced, right? You need Advanced to create a custom function. You can then use it in the regular version as well.
Jonas Löfvenmark Posted May 22, 2011 Author Posted May 22, 2011 Thanks for clarifying! For anyone else reading this thread I came up with a solution for irelating paragraphs and getting proper HTML format for lists etc. using a calculated field (textHTMLformat) on a source text field (text): Let([ $a=Evaluate(Case(IsEmpty($a);PatternCount(text;¶);$a-1)); start=Position(text;¶;0;$a)+1; end=Position(text&¶;¶;0;$a+1); mytext=Middle(text;start;end-start) ]; If($a>0;textHTMLformat;Let([$a="";$prev=""];"" )) & ¶ & Case( PatternCount(mytext;"[b] ")=0 and $prev = "list";"</ul>¶"; PatternCount(mytext;"[b] ")>0 and $prev ≠ "list";"<ul>¶" ) & Case( PatternCount(mytext;"[T] ")>0;Let($prev = "h3"; "<h3>" & Substitute(mytext;"[T] ";"") & "</h3>" ); PatternCount(mytext;"[TS] ")>0;Let($prev = "h4"; "<h4>" & Substitute(mytext;"[TS] ";"") & "</h4>") ; PatternCount(mytext;"[bT] ")>0;Let($prev = "h5"; "<h5>" & Substitute(mytext;"[bT] ";"") & "</h5>") ; PatternCount(mytext;"[b] ")>0;Let($prev = "list"; "<li>" & Substitute(mytext;"[b] ";"") & "</li>" ); Let($prev = "p"; "<p>"& mytext & "</p>" ) ) ) This code takes a source text with custom tag formatting like: [T] header para1 [TS] title para4 para5 [b] list1 [b] list2 para6 and outputs in proper HTML format as: <h3>header</h3> <p>para1</p> <h4>title</h4> <p>para4</p> <p>para5</p> <ul> <li>list1</li> <li>list2</li> </ul> <p>para6</p> Now on to character formats which in my case is extra tricky as both bold and itallic opening tags share the same closing tag like this: My words are both [cb]bold[/c] and [i]italic|/c] hence I am an important text. Any input is more than welcome!
comment Posted May 22, 2011 Posted May 22, 2011 For anyone else reading this thread I came up with a solution ... For anyone reading this thread, you included, I'd recommend against forcing recursion by referencing a calculation field to itself. Although it might seem to work in some circumstances, it's not possible to predict how it will behave under other conditions. Unlike a custom function, there is no built-in protection against stack overflow and you might easily end up with the application crashing and your file being corrupted. If you don't have the Advanced version, and you are reluctant to use a looping script (why?), you can still make recursive calculations using a repeating calculation field - see: http://fmforums.com/forum/index.php?showtopic=29250&view=findpost&p=131639
Jonas Löfvenmark Posted May 22, 2011 Author Posted May 22, 2011 Thank you, I really appreciate your feedback! The reason for not going script is that I want to dummy this down as much as possible. The FM operators need it to be as few interactions as possible. Not doing a custom function due to the client has had server failures in the past, and their technicians also need it to be as easy as possible to reinstall the systems; to me, not having a custom function makes it easier for them. However, this way seems to work fine with the data they got - if any problems occur I will probably go with a custom function! Thanks again!
comment Posted May 22, 2011 Posted May 22, 2011 The reason for not going script is that I want to dummy this down as much as possible. The FM operators need it to be as few interactions as possible. That's what script triggers are for.
Jonas Löfvenmark Posted May 23, 2011 Author Posted May 23, 2011 That's what script triggers are for. Yes, agreed. There are about a hundred scripts present for various "fixes" in their solution, and it is hard for them to keep track already.
Vaughan Posted May 23, 2011 Posted May 23, 2011 Not doing a custom function due to the client has had server failures in the past, and their technicians also need it to be as easy as possible to reinstall the systems Are you confusing custom functions with plug-ins? A cf needs nothing to be installed once the cf is in the file, and it needs nothing installed on the client computer. Regarding the hundreds of scripts for "fixes"... there is nothing "broken" in FMP that needs hundreds of fixes. It was possible to create workable solutions in FMP before script triggers were invented: the triggers merely make doing some things a bit easier -- including the option to bugger things up royally. :D
Recommended Posts
This topic is 4991 days old. Please don't post here. Open a new topic instead.
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now