How to handle comma separated decimals and floats in CF? - coldfusion

I have to validate form values as integers.
I have tried something like this:
<cfloop collection="#form#">
<cfif form.value eq int(form.value)>
#form.value# is an integer
</cfif>
</cfloop>
It works as long the user does not input comma as the decimal separator, which is the default way of doing this here in Germany.
I have to use CF MX 6.1.

It would also probably help to look into the Internatational functions that are available. LSParseNumber(), for instance.

You may, if you like, desensitize the input first.
<cfset var comma = ",">
<cfset var period = ".">
<cfset form.value = replace(form.value, comma, period, "all")>
But, if all you need is to verify if a field is an integer, why don't you look at CFLib.org - IsInt ?
<cfscript>
/**
* Checks to see if a var is an integer.
* version 1.1 - mod by Raymond Camden
*
* #param varToCheck Value you want to validate as an integer.
* #return Returns a Boolean.
* #author Nathan Dintenfass (nathan#changemedia.com)
* #version 1.1, April 10, 2002
*/
function isInt(varToCheck){
return isNumeric(varToCheck) and round(varToCheck) is vartoCheck;
}
</cfscript>

Like Al Everett, I recommend using the locale specific functions:
<!--- actually *setting* the desired locale is mandatory for this to work --->
<cfset SetLocale("German (Standard)")>
<cfif CGI.REQUEST_METHOD eq "POST">
<!--- loop the FieldNames list so only real posted values are handled --->
<cfloop list="#FORM.FieldNames#" index="FieldName">
<cfif LSIsNumeric(FORM[FieldName])>
<cfset num = LSParseNumber(FORM[FieldName])>
<!--- do stuff with #num# --->
</cfif>
</cfloop>
</cfif>

Related

ColdFusion list value replacement

I have a set of list values in ColdFusion variable, and I need to replace all the list values into desired text.
For Example:
<cfset headerColumnList = "FirstName,LastName,Email,FrequentGuestID,IP Address,Time Stamp Email Marketing">
<cfset a="test1">
<cfset b="test2">
<cfset c="test3">
<cfset d="test4">
<cfset e="test5">
<cfset f="test6">
<cfloop index = "ListElement" list= "#headerColumnList#" delimiters = ",">
<cfoutput>
#replaceList("#ListElement#","FirstName,LastName,Email,FrequentGuestID,IP Address,Time Stamp Email Marketing","#a#,#b#,#c#,#d#,#e#,#f#",",")#
</cfoutput>
</cfloop>
Output:
test1
test2
test3
test4
test5
Time Stamp test3 Marketing
In the above scenario. The value "Time Stamp Email Marketing" is supposed to be replaced with "test6" but I am getting in an alternative way where it is not replacing the phrase as a whole word. Can anyone tell me how do I replace the list phrases, any alternative for this?
Here you can use the ListQualify function to get exact result of an your scenario. So convert it in to qualify values and looping with that then you can replace it with your own list data. No need to change any order of a list values.
<cfset quoted = listQualify(headerColumnList,"''")>
<cfloop index = "ListElement" list= "#quoted#" delimiters = ",">
#replaceList(ListElement,quoted,"#a#,#b#,#c#,#d#,#e#,#f#")#
<br/>
</cfloop>
The code is working as written. You are seeing this because your check for "Email" in the replaceList() function is firing before the check for "Time Stamp Email Marketing". Notice the word "Email" in that string.
I don't know what your actual use case is but you can change the order of your code for this specific example to make it work like you want.
<cfset headerColumnList = "FirstName,LastName,Email,FrequentGuestID,IP Address,Time Stamp Email Marketing">
<cfset a="test1">
<cfset b="test2">
<cfset c="test3">
<cfset d="test4">
<cfset e="test5">
<cfset f="test6">
<cfloop index = "ListElement" list= "#headerColumnList#" delimiters = ",">
<cfoutput>
#replaceList("#ListElement#","FirstName,LastName,FrequentGuestID,IP Address,Time Stamp Email Marketing,Email","#a#,#b#,#d#,#e#,#f#,#c#",",")#
</cfoutput>
</cfloop>
This gives the desired output. Notice how I reordered the conditions within the replaceList() function.

abs not working on lucee coldfusion

I am using the below to format the number I get after calulating the % increase or decrease, which means this number can be positive or a negative number. The below works fine on Coldfusion, but on Lucee it throws an error - can't cast [- 6.50] string to a number value. Any idea how to workaround this.
<cfif money_deposit lt 0>
<cfset testVar = abs(NumberFormat(money_deposit,'99.99'))>
<cfelse>
<cfset testVar = NumberFormat(money_deposit,'99.99')>
</cfif>
You should be able to use javaCast
<cfif money_deposit lt 0>
<cfset testVar = abs(NumberFormat(javaCast("float", money_deposit),'99.99'))>
<cfelse>
<cfset testVar = NumberFormat(money_deposit,'99.99')>
</cfif>
First, remove any empty spaces. In any case, it is good practice to first test whether the input parameter is numeric.
<!--- Remove any spaces --->
<cfset money_deposit = REreplace(money_deposit,"\s","","all")>
<cfif isNumeric(money_deposit)>
<cfif money_deposit lt 0>
<cfset testVar = abs(NumberFormat(money_deposit,'-99.99'))>
<cfelse>
<cfset testVar = NumberFormat(money_deposit,'99.99')>
</cfif>
</cfif>
Number format returns a string
http://docs.lucee.org/reference/functions/numberformat.html
The problem is your formatting mask "99.99" means return a formatted number with two characters before the decimal point, the string value you are getting back is "- 6.50", with an extra space. Try using a mask for numberformat of either "9.99" or "09.99"

Coldfusion 10 cfloop errors

I am getting an error after upgrade from coldfusionOX to coldfusion 10.
Error Occurred While Processing Request Complex object types cannot be
converted to simple values.
The expression has requested a variable or an intermediate expression
result as a simple value. However, the result cannot be converted to a
simple value. Simple values are strings, numbers, boolean values, and
date/time values. Queries, arrays, and COM objects are examples of
complex values. The most likely cause of the error is that you tried
to use a complex value as a simple one. For example, you tried to use
a query variable in a cfif tag.
It occurs at line " cfloop index="local.thisRight" list="#rights#" ". It seems like ColdFusion does not like the "rights" here.
Anyone can give me some help? Thanks so much.
<cfif local.profile.rights.profile.self is not "">
<cfquery name="local.getAffiliations" datasource="#Request.readerDSN#">
SELECT tblPersonsToAffiliations.affiliationID, tblPersonsToAffiliations.rights, tblAffiliations.affiliationType, tblPersonsToAffiliations.relationshipType
FROM tblPersonsToAffiliations INNER JOIN tblAffiliations
ON tblPersonsToAffiliations.affiliationID = tblAffiliations.affiliationID
WHERE tblPersonsToAffiliations.personID IN (#local.profile.rights.profile.self#)
AND (tblPersonsToAffiliations.archived IS NULL
OR tblPersonsToAffiliations.archived = '')
</cfquery>
<cfif local.getAffiliations.recordCount is not 0>
<cfloop query="local.getAffiliations">
<cfif local.getAffiliations.relationshipType is "interested">
<cfset local.thisRelationshipType = "provisionalMember">
<cfif IsDefined("local.profile.rights.#affiliationType#.#local.thisRelationshipType#")>
<cfset local.profile.rights[affiliationType][local.thisRelationshipType] = ListAppend(local.profile.rights[affiliationType][local.thisRelationshipType], affiliationID)>
<cfelse>
<cfset local.profile.rights[affiliationType][thisRelationshipType] = affiliationID>
</cfif>
<cfelse>
<cfset local.thisRelationshipType = "fullMember">
<cfif IsDefined("local.profile.rights.#affiliationType#.#local.thisRelationshipType#")>
<cfset local.profile.rights[affiliationType][local.thisRelationshipType] = ListAppend(local.profile.rights[affiliationType][local.thisRelationshipType], affiliationID)>
<cfelse>
<cfset local.profile.rights[affiliationType][local.thisRelationshipType] = affiliationID>
</cfif>
<cfif isNull(rights)>
<cfelse>
<cfloop index="local.thisRight" list="#rights#" >
<cfif IsDefined("local.profile.rights.#affiliationType#.#local.thisRight#")>
<cfset local.profile.rights[affiliationType][local.thisRight] = ListAppend(local.profile.rights[affiliationType][local.thisRight], affiliationID)>
<cfelse>
<cfset local.profile.rights[affiliationType][local.thisRight] = affiliationID>
</cfif>
</cfloop>
</cfif>
</cfif>
</cfloop>
</cfif>
</cfif>
A bit earlier in your code you do this:
<cfif local.getAffiliations.relationshipType is "interested">
I think you need the same query name prefix in front of "rights" that is used when evaluating "relationshipType".
Try this:
#local.getAffiliations.rights#
HTH!
I am betting it is failing on this line:
<cfloop index="local.thisRight" list="rights" >
You are attempting to use the string "rights" as a list. My first reaction would be that you need to make that:
<cfloop index="local.thisRight" list="#rights#" >

ColdFusion , REGEX - Given TEXT, find all items contained in SPANs

I'm looking to learn how to create a REGEX in Coldfusion that will scan through a large item of html text and create a list of items.
The items I want are contained between the following
<span class="findme">The Goods</span>
Thanks for any tips to get this going.
You don't say what version of CF. Since v8 you can use REMatch to get an array
results = REMatch('(?i)<span[^>]+class="findme"[^>]*>(.+?)</span>', text)
Use ArrayToList to turn that into a list.
For older version use REFindNoCase and use Mid() to extract substrings.
EDIT: To answer your follow-up comment the process of using REFind to return all matches is quite involved because the function only returns the FIRST match. This means you actually have to call REFind many times passing a new startpos each time. Ben Forta has written a UDF which does exactly this and will save you some time.
<!---
Returns all the matches of a regular expression within a string.
NOTE: Updated to allow subexpression selection (rather than whole match)
#param regex Regular expression. (Required)
#param text String to search. (Required)
#param subexnum Sub-expression to extract (Optional)
#return Returns a structure.
#author Ben Forta (ben#forta.com)
#version 1, July 15, 2005
--->
<cffunction name="reFindAll" output="true" returnType="struct">
<cfargument name="regex" type="string" required="yes">
<cfargument name="text" type="string" required="yes">
<cfargument name="subexnum" type="numeric" default="1">
<!--- Define local variables --->
<cfset var results=structNew()>
<cfset var pos=1>
<cfset var subex="">
<cfset var done=false>
<!--- Initialize results structure --->
<cfset results.len=arraynew(1)>
<cfset results.pos=arraynew(1)>
<!--- Loop through text --->
<cfloop condition="not done">
<!--- Perform search --->
<cfset subex=reFind(arguments.regex, arguments.text, pos, true)>
<!--- Anything matched? --->
<cfif subex.len[1] is 0>
<!--- Nothing found, outta here --->
<cfset done=true>
<cfelse>
<!--- Got one, add to arrays --->
<cfset arrayappend(results.len, subex.len[arguments.subexnum])>
<cfset arrayappend(results.pos, subex.pos[arguments.subexnum])>
<!--- Reposition start point --->
<cfset pos=subex.pos[1]+subex.len[1]>
</cfif>
</cfloop>
<!--- If no matches, add 0 to both arrays --->
<cfif arraylen(results.len) is 0>
<cfset arrayappend(results.len, 0)>
<cfset arrayappend(results.pos, 0)>
</cfif>
<!--- and return results --->
<cfreturn results>
</cffunction>
This gives you the start (pos) and length of each match so to get each substring use another loop
<cfset text = '<span class="findme">The Goods</span><span class="findme">More Goods</span>' />
<cfset pattern = '(?i)<span[^>]+class="findme"[^>]*>(.+?)</span>' />
<cfset results = reFindAll(pattern, text, 2) />
<cfloop index="i" from="1" to="#ArrayLen(results.pos)#">
<cfoutput>match #i#: #Mid(text, results.pos[i], results.len[i])#<br></cfoutput>
</cfloop>
EDIT: Updated reFindAll with subexnum argument. Setting this to 2 will capture the first subexpression. The default value 1 captures the entire match.
Try looking into the possibility of making your HTML work with a regular DOM Parser and querying it via XPath instead of hammering this trough an regex-based abomination.
to make HTML input usable, pass it through jTidy (see http://jtidy.riaforge.org/)
Once you have well-formed XML/XHTML, build an XML document from it
<cfset dom = XmlParse(scrubbedHtml, true)>
query the XML document using XPath
<cfset result = XmlSearch(dom, "//span[#class='findme']")>
Done.
EDIT: Coldfusion's XmlSearch() doesn't have great XML namespace support. If you end up producing XHTML instead of the more recommendable XML, use the following XPath (note the colon) "//:span[#class='findme']" or "//*:span[#class='findme']". See here and here for more info.
See the jTidy API documentation for a complete overview what jTidy can do.

How to check value in an Array using Coldfusion?

I have the below code:
<cfset abcList = "*,B,b,A,C,a">
<cfset abcList=ListToArray(abcList,',')>
When I output 'abcList' then it is giving me a value but when I use the 'abcList' in <cfif> it's not working. Here is the code which is creating the problem:
<cfoutput>
#abcList[1]# <!---This is giving '*' as Correct o/p--->
<cfif #abcList[1]# eq '*'> <!---Here its going in else--->
list has * at first place
<cfelse>
* is not first
</cfif>
</cfoutput>
Any suggestions on what's wrong in my code?
You don't necessarily need to convert the list to an array. If you are starting from a list variable, you may use Coldfusion list functions to do the same thing without specifying the array conversion.
<cfset abcList = "*,B,b,A,C,a">
<cfif Compare(listGetAt(abcList, 1), '*') EQ 0>
Match
<cfelse>
No Match
</cfif>
Note that most of Coldfusion's string comparisons are not case sensitive. So if you need to test that 'B' is not the same as 'b', you will need to use the compare() function or else use one of the Regular Expression string functions. In this case, compare() returns 0 if string 1 equals string 2. If you do not need case sensitivity, then you may simplify further:
<cfset abcList = "*,B,b,A,C,a">
<cfif listGetAt(abcList, 1) EQ '*'>
Match
<cfelse>
No Match
</cfif>
It also works fine for me. Perhaps you have some extra spaces in the list values? That would skew the results:
<cfset abcList = "#chr(32)#*,B,b,A,C,a">
<cfset abcList=ListToArray(abcList,',')>
<cfoutput>
The value of abcList[1] = #abcList[1]# <br/>
<cfif abcList[1] eq '*'>
list has * at first place
<cfelse>
The else condition was hit because abcList[1] is "(space)*" and not just "*"
</cfif>
</cfoutput>
Try trimming the value first. Also, the # signs around the value are not needed.
<cfif trim(abcList[1]) eq '*'>
....
</cfif>
If that does not work, display the ascii values of both characters. Perhaps they are different than you are thinking.
<cfoutput>
ASCII abcList[1] = #asc(abcList[1])# <br/>
ASCII "*" = #asc("*")# <br/>
</cfoutput>
<cfset abcList = "*,B,b,A,C,a">
<cfset abc=ListToArray(abcList)>
<cfif #abc[1]# eq "*">OK<cfelse>FAIL</cfif>
<cfif abc[1] eq "*">OK<cfelse>FAIL</cfif>
Prints "OK OK" for me. Can you re-confirm it prints something else for you?