problem creating a select using enum values - coldfusion

i have mysql table and has a data like this
i have a table with two columns value and label and both the columns have the enum type
Data of value is:
-43200|-39600|-36000|-32400|-28800|-25200|-21600|-18000|-14400|-10800|-7200|-3600|0|3600|7200|10800|14400|18000|21600|25200|28800|32400|36000|39600|43200|46800
Data of Label is:
GMT-12:00|GMT-11:00|GMT-10:00|GMT-09:00|GMT-08:00|GMT-07:00|GMT-06:00|GMT-05:00|GMT-04:00|GMT-03:00|GMT-02:00|GMT-01:00|GMT|GMT+01:00|GMT+02:00|GMT+03:00|GMT+04:00|GMT+05:00|GMT+06:00|GMT+07:00|GMT+08:00|GMT+09:00|GMT+10:00|GMT+11:00|GMT+12:00|GMT+13:00
but as i have two columns one is for the value and other is for the label, how can i create a function which will create a select having a option value and text and create a dropdown,
if its a single column, i could have done a valuelist of valuearray and loop over it, but now its two columns, i am bit confused how to
any clue

You already know how to do this, you're just not thinking about it in context.
Two columns, two lists (or arrays).
You know you can loop over "a" list to create HTML.
So loop over BOTH lists to create HTML.
Reference each list item by position and you're good to go.
<cfset sValuesList = "-43200|-39600|-36000|etc.">
<cfset sLabelsList = "GMT-12:00|GMT-11:00|GMT-10:00|etc.">
<cfoutput>
<select>
<cfif listLen(sValuesList, "|") EQ listLen(sLabelsList, "|")>
<cfloop from="1" to="#listLen(sValuesList, "|")#" index="x">
<option value="#listGetAt(sValuesList, x, "|")#">
#listGetAt(sLabelsList, x, "|")#
</option>
</cfloop>
</cfif>
</select>
</cfoutput>

Related

How to find the nested cfoutput recordcount when using group

Consider the following:
<cfoutput query="resources" group="type">
<h4>#type#</h4>
<cfoutput>
#name#
</cfoutput>
</cfoutput>
resources.recordcount would give me the total number of records, but is there an elegant way of finding out the recordcount of the nested data? e.g
<cfoutput query="resources" group="type">
<h4>#type# (#noofrecords# of #resources.recordcount#)</h4>
<cfoutput>
#name#
</cfoutput>
</cfoutput>
I could probably do something hacky with loops, but wondered if there was a way of doing it using the cfoutput groups specifically.
You could do an output before to get the count. This would be more efficient than doing a query of queries.
<cfoutput query="resources" group="type">
<cfset noofrecords= 0>
<cfoutput>
<cfset noofrecords++>
</cfoutput>
<h4>#type# (#noofrecords# of #resources.recordcount#)</h4>
<cfoutput>
#name#
</cfoutput>
</cfoutput>
I am afraid that you would have to do some counting yourself. There is no RecordCount for the
nested grouped output, because it is really all the same query, CF is just
doing a little formatting for you.
You could get the count in the original query if you wanted an alternative method, but, you will need to test the performance before you go down this route (although using Query of Queries can also have performance issues as there are no indexes).
SELECT f1.id, f1.name, f1.type, f2.typeCount
FROM foo f1
INNER JOIN (
SELECT COUNT(type) as typeCount, type
FROM foo
GROUP BY type
) f2 on f1.type = f2.type
ORDER BY f1.type, f1.name
Then in the CF you can do:
<cfoutput query="resources" group="type">
<h4>#resources.type# (#resources.typeCount# of #resources.recordCount#)</h4>
<cfoutput>
#resources.name#
</cfoutput>
</cfoutput>
As a side note, in CF10 you can also group inside a cfloop with query like so:
<cfloop query="resources" group="type">
<h4>#resources.type# (#resources.typeCount# of #resources.recordCount#)</h4>
<cfloop>
#resources.name#
</cfloop>
</cfloop>
Another solution is:
<!--- I chose the pipe delimiter | names of things often contain commas,
otherwise, use any delimiter you like --->
<cfset TypesList = Valuelist(resources.type,"|")>
<cfoutput query="resources">
<h4>#Type# (#ListValueCount(TypesList,Type,"|")# of #resources.recordcount#)</h4>
<cfoutput>#name#</cfoutput>
</cfoutput>
While this will also work for other applications, it won't work for everything. It expects the Category count ('Type' here) to be unique (no two types with the same name). A better way to handle this is to count based on an ID rather than a name. You might have, for instance, a category setup like this
Fruits
Red Ones
Strawberries
Raspberries
Yellow Ones
Bananas
Vegetables
Green ones
Green peppers
Red Ones
Red Peppers
Tomatoes
Based on Type (as a string), the output would say Red Ones (4), Yellow Ones (1), Green Ones (1), Red Ones (4), but in a category-products relational table structure, coutning based on unique ID of the category would retrieve accurate counts.
To get the count of the nested data and display it where you say you want it, I would do this:
<cfoutput query = "rescources" group = "type">
query of queries to get the count this type
output the type and the count
<cfoutput>
output nested data
</cfoutput>
</cfoutput>

How can we add a new row in middle of a cfquery result?

I have a query result set from cfquery. I just want to add a new after a particular row number. But When tried each time it inserts the row at the end.
Is there any way I can insert row at the middle of the query?
<cfquery datasource="cse" name="abc">
select * from grade
</cfquery>
<cfset i = 0>
<cfloop query="abc">
<cfset i = i+1>
<cfif i eq 2>
<cfset queryAddRow(abc)>
</cfif>
</cfloop>
You cannot, easily. You have a coupla options.
<cfquery name="resultSet" dbtype="query">
SELECT col1, col2, etc
FROM yourQuery
WHERE [somecondition matching the "top" rows]
UNION
SELECT 'value' AS col1, 'value' AS col2, etc
UNION
SELECT col1, col2, etc
FROM yourQuery
WHERE [somecondition matching the "bottom" rows]
</cfquery>
Or you could simply loop over the original query, building a new query, using queryNew(), queryAddRow() and querySetCell(). At the appropriate point in the loop... add the row you want to insert, then continue adding the rest of them.
There's no elegant way I can think of.
Not knowing the goal you are trying to accomplish, my first advice would be along the lines of the other answers. Add rows that you can subsequently sort using Order By. However, if you really just want to inject a row at a specific position in the existing query, this should do it for you. Note you'll need to define the columns in the QueryNew(), so I've provided a sample case.
<cfquery datasource="cse" name="abc">
select student, teacher from grade
</cfquery>
<cfset abc_new = QueryNew("student,teacher","varchar,varchar")>
<cfloop query="abc">
<!--- ADD NEW DATA TO QUERY AT ROW 2 --->
<cfif CURRENTROW eq 2>
<cfset QueryAddRow(abc_new) />
<cfset QuerySetCell(abc_new,"STUDENT","Tommy Oliver") />
<cfset QuerySetCell(abc_new,"TEACHER","Ms. Appleby") />
</cfif>
<!--- COPY ORIGINAL DATA TO QUERY, ROW NUMBERS NOT PRESERVED --->
<cfset QueryAddRow(abc_new) />
<cfset QuerySetCell(abc_new,"STUDENT",abc.STUDENT) />
<cfset QuerySetCell(abc_new,"TEACHER",abc.TEACHER) />
</cfloop>
<cfdump var="#abc_new#">
The best way would be to create a new query, copying each row from the original but adding the new row at the required point.
Use QueryNew( ) to create the new query.
A bit like copying text files line-by-line and inserting a new line in the middle!
Again, not quite sure you'd need to do this - you could simply add a sortorder column, incrementing in 10s for each row. The new row would then have a sortorder in between the row before and the row after. eg sortorder would be 15 to insert between 10 and 20.
Hope this helps!
I assume row positions in your recordset are based on what you ORDER BY'd in your initial CFQUERY.
Therefore, I'd add the row to the recordset, then do a query of that recordset (query of query) using the same ORDER BY as the initial query, which should then return all rows including your new one, in the (presumed) proper order, in a new recordset.

Insert data from form with dynamically named fields

OK. I've done a terrible job of explaining what I'm trying to do. I will try one more time to be more clear.
I have a list of variables that is submitted to a page with a cfquery insert. The variables come from dynamically named form fields, and are captured using a cfloop:
<cfloop list="#form.fieldnames#" index="item">
</cfloop>
What I have are form fields dynamically named, and a value added, as such:
<input type="hidden" name="ticketid_#some_number#" value="#some_quantity#">
For brevity, lets say the form field name is ticketid_6, and the value is 4. This could be a different name and value (for instance, ticketid_3 with a value of 1), or there might be several form fields of similar construct with different names and/or values.
So, on the insert page, I need to insert ticketid_6 4 times (creating 4 separate rows) into my table. So, a row in the database for each dynamically named form field, times the value of each.
I hope that explains it better.
Leigh,
I am still open to your suggestion on the previous post, but I fear I might not have explained my situation clearly enough for you to give your best recommendation. I will re-approach that question after I get this part figured out.
If you need to loop through all your field names and treat each one of those fields as a list you'd need to do two loops to insert each item.
<cfloop list="#form.fieldnames#" index="item"><!--- loop through all the form fields --->
<cfif find('ticketid_',item)><!--- if the form name contains 'ticketid_'. Use findNoCase if you want to ignore case sensitivity --->
<cfloop from="1" to="#form[item]#" index="counter"><!--- loop through the number in form.ticketid_ --->
<cfquery datasource="#dsn#">
INSERT INTO table (fieldname, fieldValue, TicketNum)
VALUES (
<cfqueryparam value="#item#" cfsqltype="cf_sql_varchar">,--fieldName from the form
<cfqueryparam value="#form[item]#" cfsqltype="cf_sql_varchar">--value of the fieldName in the form
<cfqueryparam value="#counter#" cfsqltype="cf_sql_integer">--ticket number being inserted
)
</cfquery>
</cfloop>
</cfif>
</cfloop>
You'll need to do server side validation to verify they haven't entered a non numeric number for the input box, but assuming you've done that this should achieve what you're looking for.
You need to use Evaluate function to get form dynamically input field value
Try this one
<input type="hidden" name="ticketid_#some_number#" value="#some_quantity#">
<cfloop list="#form.fieldnames#" index="item">
<cfoutpuy>Evaluate("ticketid_#item#")</cfoutpuy>
</cfloop>
You need to first bundle your data into an XML structure
<cfsavecontent variable="myFormData">
<cfoutput>
<ul class="xoxo">
<cfloop list="#form.fieldnames#" index="item">
<cfloop list="#form[item]#" index="eachItem">
<li><b>#xmlformat(item)#</b> <var>#xmlformat(eachItem)#</var>
</cfloop>
</cfloop>
</ul>
<cfoutput>
</cfsavecontent>
Then do a single insert
<cfquery>
INSERT INTO table (formData)
VALUES (<cfqueryparam value="#myFormData#" cfsqltype="cf_sql_varchar">)
</cfquery>
When you pull the data, you can
Show it as is, a bulleted list,
Promote to a bunch of rows in a table
Note that the data is inserted as both HTML and XML

How can I use dynamically generated variables from cfloop individually?

I'm not sure my title explains this very well. Frankly, I'm not sure how to put it into words, but here goes:
I am capturing variables from dynamically created form fields on another page, that have been submitted to a page containing the code below. So far, everything works as I want it to. I'm getting the dynamically named form fields. Now I need to add the subtotal dollar amounts together to create a grand total. Unfortunately, I can't figure out how to get the individual totals out of the loop so I can do the math for the final number, due to their dynamic nature.
This part of the code below generates the subtotals, and I need to be able to add all of them together to get a grand total, but I can't figure out how:
#dollarformat(val(getticket[item].ticketprice * form[item]))#
Maybe I need to take a different approach...suggestions/help appreciated.
Here's the full code:
<CFLOOP LIST="#form.fieldnames#" INDEX="item">
<cfoutput>
<cfquery datasource="outertixdb" name="getticket[item]">
select * from tickets
where ticketid = '#item#'
</cfquery>
#getticket[item].ticketname#: #dollarformat(getticket[item].ticketprice)# x #form[item]# = #dollarformat(val(getticket[item].ticketprice * form[item]))#<br/>
</cfoutput>
You would need to set the name attribute of your cfquery using the following format:
<cfquery datasource="outertixdb" name="#getticket[item]#">
To handle the total, you would first need a variable before the cfloop
<cfset total = 0 />
Then, inside the loop, you simply add the price of the ticket to the total
<cfset total = total + getticket[item].ticketprice />
Also, you should be using cfqueryparam in your query. You can read more about it here
Lastly, if you do not need all the data in the tickets table, do not use 'select *..', only pull pack the data that you need.
Not sure I completely understand, but it sounds like you are simply trying to look up a bunch of ticket records, by "id". Then display the individual costs, plus a grand total. If that is all your doing, just give the fields the same name: ticketID. For example:
<input name="ticketID" value="1" ...>
<input name="ticketID" value="22" ...>
<input name="ticketID" value="45" ...>
<input name="ticketID" value="16" ...>
Then the values will be submitted as a list ie 1,22,45,16, which you can feed into your query using an IN clause. That lets you grab all of the data in a single query. (Generally you want to avoid running queries within a loop because performing a separate database query for each id generates a lot of unnecessary overhead and degrades performance).
* Change the cfsqltype as needed
SELECT TicketID, TicketPrice
FROM YourTable
WHERE TicketID IN ( <cfquerparam value="#FORM.ticketID#"
list="true"
cfsqltype="cf_sql_integer">
)
UPDATE:
form[item] is the value of the quantity select from the previous page.
That is a confusing naming convention. I would recommend using a slightly more intuitive name like "quantity". Something more descriptive of the contents. You can still use the ticket id to generate unique names, ie quantity_#ticketID#. For example, using the same ticket id's as above:
<input name="quantity_1" ...>
<input name="quantity_22" ...>
<input name="quantity_45" ...>
<input name="quantity_16" ...>
Once you have the results, there are several ways to generate a grand total. The simplest being to initialize a variable before your loop, then increment it as you iterate. Use the query ticket ID to grab the quantity value from the FORM scope:
<cfset grandTotal = 0>
<cfoutput query="yourQuery">
<!--- extract quantity value --->
<cfset currQuantity = FORM["quantity_"& yourQuery.ticketID ]>
... display price ...
<cfset grandTotal += val(yourQuery.ticketPrice * currQuantity )>
</cfoutput>
GrandTotal <cfoutput>#grandTotal#</cfoutput>
I would recommend throwing out the whole dynamically named query thing.
<cfset total = 0>
<CFLOOP LIST="#form.fieldnames#" INDEX="item">
<cfquery datasource="outertixdb" name="getticket">
select * from tickets
where ticketid = <cfqueryparam cfsqltype="cf_sql_varchar" value="#item#">
</cfquery>
<cfset total += getticket.ticketprice />
<cfoutput query="getTicket">
#ticketname#: #dollarformat(ticketprice)# × #form[item]#
= #dollarformat(val(ticketprice * form[item]))#<br/>
</cfoutput>
</cfloop>
Output your total as needed

coldfusion query loop not cooperating

I'm trying to create a function to create csv files from queries. After I run the query, I'm looping through it and appending each row's fields to a StringBuffer object. To that end, I'm putting the column names into an array:
<cfset indexes = #ListToArray(Arguments.header)# />
where the argument is currently a string like:
"col1, col2, col3...."
I've verified that both the query and the array are what they should be by dumping.
The trouble comes when looping through the query results. Given:
<cfset indexes_length = #ArrayLen(indexes)# />
<cfloop query="query_for_csv">
<cfloop index="i" from="1" to="#indexes_length#">
<cfset attr = #indexes[i]# />
<cfset sbOutput.Append(
"#query_for_csv[attr][query_for_csv.CurrentRow]#") />
</cfloop>
</cfloop>
Only the first value of the first row is output before I get the error message:
[Table (rows 10 columns col1, col2, col3):
[col1: coldfusion.sql.QueryColumn#6f731eba]
[col2: coldfusion.sql.QueryColumn#6ee67e7f]
[col3: coldfusion.sql.QueryColumn#5c6647cb]
is not indexable by col2
If I replace the variable #attr# with the literal "col2":
#query_for_csv['col2'][query_for_csv.CurrentRow]#
then the loop sails through with no problem, and spits out all the values indexed by 'col2'. Any ideas?
I would guess it's the spaces in your header list that is the problem, so probably this would work:
<cfset attr = trim(indexes[i]) />
However, since you're not using them, you probably don't need that and can just do this...
<cfloop query="QueryName">
<cfloop index="CurCol" list=#QueryName.ColumnList# >
<cfset sbOutput.Append(
QueryName[CurCol][QueryName.CurrentRow]
)/>
</cfloop>
</cfloop>
p.s.
You'll note here that there's only one pair of hashes - there only needs to be one pair in your original code snippets too (in the to attribute) - the rest are unnecessary noise.
As has already been said before, try to avoid spaces before or after a list element.
In case you want to compare notes, check out the approach Ben Nadel chose to implement such a Query2CSV converter: http://www.bennadel.com/blog/1239-Updated-Converting-A-ColdFusion-Query-To-CSV-Using-QueryToCSV-.htm