Coldfusion/SQL: Element Id is not defined in form - sql

When I attempt to delete an item in a shopping cart. I get a "Element Id is not defined in form" error.
Where am I going wrong?
I'm using MSSQL 2008 r2, Coldfusion 10.
Summary:
tickets.cfm this is the page that displays the products, also contains a form with hidden values to be passed on to cart_manage.cfm.
cart_manage.cfm is an action page for both tickets.cfm and cartlist.cfm
cartlist.cfm is a page that displays the shopping cart contents.
application.cfm session variables.
application.cfm
<cfapplication sessionmanagement="yes">
<cfapplication name="cart" clientmanagement="Yes"
sessionmanagement="Yes"
sessiontimeout="#CreateTimeSpan(0,0,15,0)#"
applicationtimeout="#CreateTimeSpan(0,2,0,0)#">
<cfparam name="session.allowin" default="false">
tickets.cfm
<cfif NOT IsDefined('SESSION.cart')>
<cfset SESSION.cart = ArrayNew(1) />
</cfif>
<cfquery datasource="sqltest" name="getTickets">
select *,
CASE WHEN Friday=1and Saturday=1and Sunday=1
THEN 'All three days'
WHEN Friday=0and Saturday=0and Sunday=0
THEN 'None'
ELSE
STUFF(
case when Friday=1 then ',Friday' else '' end
+ case when Saturday=1 then ',Saturday' else '' end
+ case when Sunday=1 then ',Sunday' else '' end, 1,1,'')
END WhichDays
from tickets_performances;
</cfquery>
<table width="600" border="0">
<tr>
<td>Day</td>
<td>Price</td>
<td>How Many Left</td>
<td>Quantity</td>
</tr>
<p> You can only purchase a maximum of two tickets at a time. Having a ticket limit ensures fairness to all those buying tickets. The ticket limit applies per account, billing address, and/or credit card. Please observe the ticket limit as over purchases may be cancelled without notice or warning. </p>
<cfform action="cart_manage.cfm" name="form" method="post">
<cfoutput query="getTickets">
<tr>
<td>#WhichDays#</td>
<td>£#price#</td>
<td>#stock#</td>
<td><cfinput type="text" id="quantity" name="quantity" size="5" class="field" maxlength="1" value="0"/></td>
<td><cfinput type="hidden" name="id" value="#getTickets.ticket_performanceID#" />
<cfinput type="hidden" name="item" value="#getTickets.WhichDays#" />
<cfinput type="hidden" name="price" value="#getTickets.price#" />
<cfinput type="submit" name="add_button" value="Add to Cart"></td>
</tr>
</cfoutput>
</cfform>
</table>
cart_manage.cfm
<cfset newitem = 0>
<cfloop from="1" to="#arrayLen(session.cart)#" index="i">
<cfif session.cart[i].itemid EQ #form.id#>
<cfset session.cart[i].quantity = session.cart[i].quantity + #form.quantity#>
<cfset newitem = 1>
<cfbreak>
</cfif>
</cfloop>
<cfif newitem EQ 0>
<cfset temp = arrayAppend(session.cart, structNew())>
<cfset session.cart[arrayLen(session.cart)].itemid = #form.id#>
<cfset session.cart[arrayLen(session.cart)].item = #form.item#>
<cfset session.cart[arrayLen(session.cart)].quantity = #form.quantity#>
<cfset session.cart[arrayLen(session.cart)].price = #form.price#>
<cflocation url="cartlist.cfm">
</cfif>
<cfif IsDefined('FORM.delete_button.y')>
<cfloop from="#ListLen(FORM.delete_index)#" to="1" index="i" step="-1">
<cfset ArrayDeleteAt(SESSION.cart, ListGetAt(FORM.delete_index, i))>
</cfloop>
<cflocation url="cartlist.cfm">
<cfelseif IsDefined('FORM.update_button.y')>
<cfloop from="1" to="#ArrayLen(SESSION.cart)#" index="i">
<cfset SESSION.cart[i].quantity = FORM["quantity_" & i] >
</cfloop>
<cflocation url="cartlist.cfm">
<cfelseif IsDefined('FORM.checkout_button.y')>
<cflocation url="checkout.cfm">
</cfif>
<cflocation url="cartlist.cfm">
cartlist.cfm
<cfset nTotal = 0 />
<cfform action="cart_manage.cfm" method="post">
<table width="100%">
<tr valign="top">
<td>
<table width="100%" class="white">
<tr>
<td class="tblehead"> </td>
<td class="tblehead">Item</td>
<td class="tblehead">Price Per Item</td>
<td class="tblehead">Quantity</td>
<td class="tblehead">Price</td>
</tr>
<cfoutput>
<cfloop from="1" to="#ArrayLen(SESSION.cart)#" index="i">
<tr>
<td height="40" width="40" align="center" class="dkturq">
<cfinput type="checkbox" name="delete_index" value="#i#" />
</td>
<td height="40" class="dkturq">
#SESSION.cart[i].item#
</td>
<td height="40" class="dkturq">
£#(SESSION.cart[i].price)#
</td>
<td height="40" class="dkturq">
<cfinput type="text" name="quantity_#i#" value="#SESSION.cart[i].quantity#" size="5" class="field" />
</td>
<td height="40" class="dkturq">
<cfset nPrice = SESSION.cart[i].quantity * SESSION.cart[i].price />
<cfset nTotal = nTotal + nPrice />
£#(nPrice)#
</td>
</tr>
</cfloop>
</cfoutput>
</table>
</td>
<td></td>
<td>
<table width="100%" height="100%" class="white">
<tr>
<td class="tblehead">
Summary
</td>
</tr>
<tr>
<td class="dkturq">
total:
<cfoutput>£#(nTotal)#</cfoutput>
<br /><br /><br /><br />
Clear Shopping Cart
<cfinput type="submit" name="update_button" id="update_button" value="update" />
<cfinput type="submit" name="delete_button" id="delete_button" value="delete" /><br /></a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</cfform>
CFDUMP of FORM
CFDUMP of Session.cart
Error:
CFDUMP when I press delete

Thanks to Leigh, I managed to get it to work.
(Summary from the chat ..)
The original problem is pretty much what the error message said. ie Trying to use a form field that does not exist. The cause is "tickets.cfm" and "cartList.cfm" contain different form fields. The form in "cartList.cfm" does not contain a field named form.id, hence the error when that form is submitted. To avoid the error you need to verify the form.id exists, with structKeyExists() before accessing it.
However, we decided to revise the action page code instead. Also, the "cartList.cfm" form was changed to use itemID instead of index. Reason being, the index can change which might cause the wrong item to be deleted or updated. There is still room for improvement, but here is the jist of the changes:
*cartList.cfm (form fields) *
<!--- use itemID's instead of "index" in all form fields --->
<cfinput type="checkbox" name="delete_itemID" value="#SESSION.cart[i].itemid#" />
<cfinput type="text" name="quantity_#SESSION.cart[i].itemid#" value="#SESSION.cart[i].quantity#" size="5" class="field" /><br>
cartManage.cfm
<!--- ADD item to cart ---->
<cfif structKeyExists(FORM, "add_button")>
... code to add items here ...
<!--- DELETE from cart ---->
<cfelseif structKeyExists(FORM, "delete_button")>
<!---
Ensure the field exists to prevent errors. Note: A more
efficient option is to test the field's existence in the cfelseif
--->
<cfparam name="FORM.delete_itemID" default="">
<cfloop from="#ArrayLen(SESSION.cart)#" to="1" index="i" step="-1">
<!--- if this item was marked as "deleted", remove it --->
<cfif listFind(FORM.delete_itemID, SESSION.cart[i].itemID)>
<cfset arrayDeleteAt(SESSION.cart, i)>
</cfif>
</cfloop>
<!--- UPDATE item in cart ---->
<cfelseif structKeyExists(FORM, "update_button")>
<cfloop from="1" to="#ArrayLen(SESSION.cart)#" index="i">
<cfset currentItem = session.cart[i]>
<!--- Note: For safety, verify the field exists first --->
<cfset currentItem.quantity = FORM["quantity_" & currentItem.itemID] >
</cfloop>
</cfif>

Related

Compare two table row values ColdFusion?

I have two queries and each query is outputted on the screen in separate table. Both quires have the same number of records but I would like to check if each field is equal if not I want to set different background color for that table row. Here is the code that I have so far:
<cfquery name="oldData" datasource="test">
SELECT
old_id,
old_userid,
old_first,
old_last,
old_dob
FROM OldTest
</cfquery>
<cfquery name="newData" datasource="test">
SELECT
new_id,
new_userid,
new_first,
new_last,
new_dob
FROM NewTest
</cfquery>
And here is code for both tables:
<table>
<tr>
<td valign="top">
<table class="oldData">
<caption>Old Data</caption>
<thead>
<tr>
<th>ID</th>
<th>UserID</th>
<th>First</th>
<th>Last</th>
<th>DOB</th>
<tr>
</thead>
<tbody>
<cfoutput query="oldData">
<tr>
<td>#old_id#</td>
<td>#Trim(old_userid)#</td>
<td>#Trim(old_first)#</td>
<td>#Trim(old_last)#</td>
<td>#Trim(old_dob)#</td>
</tr>
</cfoutput>
</tbody>
</table>
</td>
<td valign="top">
<table class="newData">
<caption>New Data</caption>
<thead>
<tr>
<th>ID</th>
<th>UserID</th>
<th>First</th>
<th>Last</th>
<th>DOB</th>
<tr>
</thead>
<tbody>
<cfoutput query="newData">
<tr>
<td>#new_id#</td>
<td>#Trim(new_userid)#</td>
<td>#Trim(new_first)#</td>
<td>#Trim(new_last)#</td>
<td>#Trim(new_dob)#</td>
</tr>
</cfoutput>
</tbody>
</table>
</td>
</tr>
</table>
I'm wondering if I should compare data rows before the output something like:
<cfif oldData.old_first[currentrow] NEQ newData.new_first[currentrow]>
<cfset rowColor = "red">
</cfif>
Or there is better way to approach this. If anyone knows better way please let me know.
I would use looping:
<cfloop from="1" to="#oldData.recordCount#" index="r">
Question #oldData.old_id[r]# = #oldData.new_id[r]#? Answer: #oldData.old_id[r] eq oldData.new_id[r]#<br>
</cfloop>
You can wrap the loop around TRs and TDs if you desire.
This method also eliminates the need for a QofQ, which are resource intensive.
I suggest a query of queries resembling this:
select 'same' comparison, field1, field2, etc
from query1, query2
where query1.someField = query2.someField
union
select 'different' comparison, field1, field2, etc
from query1
where somefield not in (<cfqueryparam value="#valueList(query2.someField#") list = true>
Your table row colour can be specified with a ternary operator.
<tr bgcolor="#comparison is 'same' ? 'white' : 'red'#">

ColdFusion Multiple cfif conditions only returns the 1st condition

I am new to ColdFusion and have to make a edit page that will both update and track the changes made to a table; while passing the logged in AD user to the database.
Environment:
DB: SQL 2008 R2
OS: Windows 8
Server: ColdFusion 8
Tables Involved:
Branches (main data)
Audit_Branches (change tracking data)
Files involved:
editBranch.cfm (form)
updateBranch.cfc (updates Branches table)
auditBranchLog.cfc (updates Audit_Branches table)
So far I have built the page, and have added the functionality to update the Branches table. Now, I am trying to track the changes and log the AD user who made them.
I started by using a SQL Trigger to watch for Inserts, Updates, Deletes on the Branches table; but the SQL Server only tracks the current SQL user. Since that user is a application user, all the users have the same name entry. Consequently, I re-engineered the Audit_Branches table to have the data inserted directly via CF and thus I can pass the AD username.
Main Problem:I can get the first of three fields to insert into the Audit_Branches table. If more than one field has a change, only the first one in the Arguments array is run and the others are ignored.
I am using cf-if statements to add to a query that is then being passed via a cf-invoke to the auditBranchLog function.
I have tried nested if, if-else; and and/or statements all to no avail. Please help me figure out the best way to make the updateBranch go through all the ifs one by one or suggest a better way to pass the information along to the auditBranchLog
Much Thanks...
------------------ editBranch code:
<cfquery name="getBranches" datasource=[...]>
SELECT
BRANCHID,
BRANCHDESCRIPTION,
BRANCHFILTER,
ADDRESS1,
[...]
FROM Branches
where BRANCHID = '#URL.BRANCHID#'
</cfquery>
<script>
function updateBranch(){
var branchID = $('#branchID').val() ;
var branchDescription = $('#branchDescription').val() ;
var branchDescription_Old = $('#branchDescription_Old').val() ;
var branchFilter = $('#branchFilter').val();
var branchFilter_Old = $('#branchFilter_Old').val() ;
var address1 = $('#address1').val();
var address1_Old = $('#address1_Old').val();
[...]
$.ajax(
{
// the location of the CFC to run
url: "updateBranch.cfc"
// send a GET HTTP operation
, type: "get"
// send the data to the CFC
, data: {
// the method in the CFC to run
method: "UpdateBranches"
// send the BranchID
, branchID: branchID
, branchDescription: branchDescription
, branchDescription_Old: branchDescription_Old
, branchFilter: branchFilter
, branchFilter_Old: branchFilter_Old
, address1: address1
, address1_Old: address1_Old
[...]
}
// this gets the data returned on success
, success: function doLoad(data) { if (typeof console != "undefined") {
console.log(data);
}; location.href = "BranchList.cfm";
}
} )
}
</script>
</head>
<body>
<cfoutput>
<form class="form-horizontal" action="" method="post">
[...]
<fieldset>
<!-- Form Name -->
<legend>Edit Branch</legend>
<!-- BRANCHID input-->
<div class="form-group">
<label class="col-md-4 control-label" for="branchID">Branch ID</label>
<div class="col-md-4">
<input id="branchID" class="form-control input-md" name="branchID" type="text" placeholder=""
value="#getBranches.BRANCHID#" readonly="yes">
</div>
</div>
<!-- BRANCHDESCRIPTION input-->
<div class="form-group">
<label class="col-md-4 control-label" for="branchDescription">Branch Description</label>
<div class="col-md-4">
<input id="branchDescription" class="form-control input-md" name="branchDescription"
value="#getBranches.BRANCHDESCRIPTION#" type="text" placeholder="">
<input id="branchDescription_Old" name="branchDescription_Old" value="#getBranches.BRANCHDESCRIPTION#"
type="hidden">
</div>
</div>
<!-- BRANCHFILTER input-->
<!--- using CFSelect allows to get the db field back for the current selection --->
<div class="form-group">
<label class="col-md-4 control-label" for="branchFilter">Branch Filter</label>
<div class="col-md-4">
<select id="branchFilter" class="form-control" name="branchFilter" size="1">
<cfif LEN(getBranches.branchFilter) GT 0>
<option value="#getBranches.branchFilter#" selected>#getBranches.branchFilter# (current value)</option>
<option value="#getBranches.branchFilter#">---</option>
</cfif>
<option value="Branch">Branch</option>
<option value="Headquarters">Headquarters</option>
<option value="RDC">RDC</option>
<option value="Automation">Automation</option>
</select>
<input id="branchFilter_Old" name="branchFilter_Old" value="#getBranches.BRANCHFILTER#"
type="hidden">
</div>
</div>
<!-- ADDRESS1 input-->
<div class="form-group">
<label class="col-md-4 control-label" for="address1">Address 1</label>
<div class="col-md-4">
<input id="address1" class="form-control input-md" name="address1" type="text"
value="#getBranches.ADDRESS1#" placeholder="">
<input id="address1_Old" name="address1_Old" value="#getBranches.ADDRESS1#"
type="hidden">
</div>
</div>
[...]
<!-- SUBMIT Button -->
<div class="form-group">
<label class="col-md-4 control-label" for="SUBMIT"></label>
<div class="col-md-4">
<button type = "button" id="SUBMIT" class="btn btn-primary" name="SUBMIT" onClick="updateBranch()">Submit</button>
</div>
</div>
------------------ updateBranch code:
<cfcomponent displayname="Branches" access="remote" hint="Update Branches">
<cffunction name="getUserID" displayname="getUserID" hint="I pass back the user information in a clean format" access="package" output="false">
<cfset var UserID = "">
<cfset UserID = [...] >
<cfreturn UserID>
</cffunction>
<cffunction name="UpdateBranches" access="remote" returntype="string"
hint="Changes the Branch Info" >
<cfargument name="branchID" />
<cfargument name="branchDescription" />
<cfargument name="branchDescription_Old" />
<cfargument name="branchFilter" />
<cfargument name="branchFilter_Old" />
<cfargument name="address1" />
<cfargument name="address1_Old" />
<cfset auditLog = QueryNew("BranchID,FieldName,Old,New,UserID", "VarChar, VarChar, VarChar, VarChar, VarChar")>
<!--- compare old a new and call auditBranchLog.cfc --->
<!---BranchDescription--->
<cfif "#ARGUMENTS.branchDescription#" NEQ "#ARGUMENTS.branchDescription_Old#">
<cfset newrow = QueryAddRow(auditLog)>
<cfset temp = QuerySetCell(auditLog,"BranchID","#ARGUMENTS.branchID#")>
<cfset temp = QuerySetCell(auditLog,"FieldName","BranchDescription")>
<cfset temp = QuerySetCell(auditLog,"Old","#ARGUMENTS.branchDescription_Old#")>
<cfset temp = QuerySetCell(auditLog,"New","#ARGUMENTS.branchDescription#")>
<cfset temp = QuerySetCell(auditLog,"UserID","#getUserID()#")>
</cfif>
<!---BranchFilter--->
<cfif "#ARGUMENTS.branchFilter#" NEQ "#ARGUMENTS.branchFilter_Old#">
<cfset newrow = QueryAddRow(auditLog)>
<cfset temp = QuerySetCell(auditLog,"BranchID","#ARGUMENTS.branchID#")>
<cfset temp = QuerySetCell(auditLog,"FieldName","BranchFilter")>
<cfset temp = QuerySetCell(auditLog,"Old","#ARGUMENTS.branchFilter_Old#")>
<cfset temp = QuerySetCell(auditLog,"New","#ARGUMENTS.branchFilter#")>
<cfset temp = QuerySetCell(auditLog,"UserID","#getUserID()#")>
</cfif>
<!---Address1--->
<cfif "#ARGUMENTS.address1#" NEQ "#ARGUMENTS.address1_Old#">
<cfset newrow = QueryAddRow(auditLog)>
<cfset temp = QuerySetCell(auditLog,"BranchID","#ARGUMENTS.branchID#")>
<cfset temp = QuerySetCell(auditLog,"FieldName","Address1")>
<cfset temp = QuerySetCell(auditLog,"Old","#ARGUMENTS.address1_Old#")>
<cfset temp = QuerySetCell(auditLog,"New","#ARGUMENTS.address1#")>
<cfset temp = QuerySetCell(auditLog,"UserID","#getUserID()#")>
</cfif>
<cfif auditLog.RecordCount NEQ 0>
<cfinvoke component="auditBranchLog" method="auditBranch" auditLog="#auditLog#" >
</cfif>
<cfquery name=[...]
</cfquery>
<cfreturn arguments.branchID />
</cffunction>
</cfcomponent>
------------------ auditBranchLog code:
<cffunction name="auditBranch" displayname="auditBranch" >
<cfargument name="auditLog" type="query" required="true">
<cfquery name="auditBranchQry" datasource=[...]>
USE [...]
INSERT INTO [dbo].[Audit_BRANCHES]
([BranchID]
,[FieldName]
,[Old]
,[New]
,[ChangeDate]
,[UserID])
VALUES
(
<CFQUERYPARAM CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#auditLog.BranchID#" />
,<CFQUERYPARAM CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#auditLog.FieldName#" />
,<CFQUERYPARAM CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#auditLog.Old#" />
,<CFQUERYPARAM CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#auditLog.New#" />
,getdate()
,<CFQUERYPARAM CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#auditLog.UserID#" />
)
</cfquery>
<cfset testVar = "true">
<cfreturn testVar>
</cffunction>
</cfcomponent>
UPDATE:
Here is the information from the cfdump, I changed all three values:
<th class="query" colspan="6" onClick="cfdump_toggleTable(this);" style="cursor:pointer;" title="click to collapse">query</th>
</tr>
<tr bgcolor="eeaaaa" >
<td class="query" style="cursor:pointer;" title="click to collapse" onClick="cfdump_toggleRow_qry(this);"> </td>
<td class="query">BRANCHID</td>
<td class="query">FIELDNAME</td>
<td class="query">NEW</td>
<td class="query">OLD</td>
<td class="query">USERID</td>
</tr>
<tr >
<td style="cursor:pointer;" title="click to collapse" onClick="cfdump_toggleRow_qry(this);" class="query">1</td>
<td valign="top">YYZ </td>
<td valign="top">BranchDescription </td>
<td valign="top">BranchLabel-New </td>
<td valign="top">BranchLabel </td>
<td valign="top">user.name </td>
</tr>
<tr >
<td style="cursor:pointer;" title="click to collapse" onClick="cfdump_toggleRow_qry(this);" class="query">2</td>
<td valign="top">YYZ </td>
<td valign="top">BranchFilter </td>
<td valign="top">Branch </td>
<td valign="top">Headquarters </td>
<td valign="top">user.name </td>
</tr>
<tr >
<td style="cursor:pointer;" title="click to collapse" onClick="cfdump_toggleRow_qry(this);" class="query">3</td>
<td valign="top">YYZ </td>
<td valign="top">Address1 </td>
<td valign="top">Address1-new </td>
<td valign="top">Address1 </td>
<td valign="top">user.name </td>
</tr>
</table>
<wddxPacket version='1.0'><header/><data><string>YYZ</string></data></wddxPacket>
I found out what I was doing wrong from a fellow worker bee here in the office.
I simply needed to wrap the cfquery in the auditBranchLog in cfoutput tags like thus:
<cfoutput query="arguments.auditLog">
<cfquery name="auditBranchQry" datasource="[...]">
[...]
</cfquery>
</cfoutput>
This allowed ColdFusion to loop through the query.
I feel rather sheepish.
Thank you James for your help, it did get me looking outside of the answer I was seeking.
On this code
<!---BranchDescription--->
<cfif "#ARGUMENTS.branchDescription#" NEQ "#ARGUMENTS.branchDescription_Old#">
<cfset newrow = QueryAddRow(auditLog)>
<cfset temp = QuerySetCell(auditLog,"BranchID","#ARGUMENTS.branchID#")>
<cfset temp = QuerySetCell(auditLog,"FieldName","BranchDescription")>
<cfset temp = QuerySetCell(auditLog,"Old","#ARGUMENTS.branchDescription_Old#")>
<cfset temp = QuerySetCell(auditLog,"New","#ARGUMENTS.branchDescription#")>
<cfset temp = QuerySetCell(auditLog,"UserID","#getUserID()#")>
</cfif>
<!---Address1--->
<cfif "#ARGUMENTS.address1#" NEQ "#ARGUMENTS.address1_Old#">
<cfset newrow = QueryAddRow(auditLog)>
<cfset temp = QuerySetCell(auditLog,"BranchID","#ARGUMENTS.branchID#")>
<cfset temp = QuerySetCell(auditLog,"FieldName","Address1")>
<cfset temp = QuerySetCell(auditLog,"Old","#ARGUMENTS.address1_Old#")>
<cfset temp = QuerySetCell(auditLog,"New","#ARGUMENTS.address1#")>
<cfset temp = QuerySetCell(auditLog,"UserID","#getUserID()#")>
</cfif>
<cfif auditLog.RecordCount NEQ 0>
<cfinvoke component="auditBranchLog" method="auditBranch" auditLog="#auditLog#" >
</cfif>
It looks like you are pushing a query in some sort of ORM Style.
It would be useful to consider
<cfdump var="#auditlog#">.
Having one function for each action rather than a single auditBranch
Seeing all those QuerySetCell() makes me think a different approach may be needed.
UPDATE
The following is suggested
<cfdump var="#auditlog#">
<cfif auditLog.RecordCount NEQ 0>
<cfinvoke component="auditBranchLog" method="auditBranch" auditLog="#auditLog#" >
</cfif>

Generating dynamic cfdocument - need variable font size

I have a CFML page that allows a user to input quite a bit of info and save it (MS SQL). Then they can create a psuedo report page that's contained in a textarea.
<cfform action="index.cfm?fa=customReportAction" method="post">
<cfif benchInfo.custom_report EQ "" or attributes.submit eq "Generate New Reports">
<cfif attributes.submit eq "Generate New Reports">
This is a new version of the report<br>
</cfif>
<cftextarea name="custom_report" richtext="true" value="#body_temp#" width="1000" height="600">
<cfoutput>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<div align="center" >
<br />
<br />
<div>
<img src="#replace(request.controlurl,'https','http')#images/Logo.png" />
</div>
<br />
<br />
<div style="font-size:20px; font-weight:bold; padding-top:25px;">Benchmark Comparative Study
<br />
Summary</div>
<div style="padding-top:10px; "><h2>
#benchInfo.name#
</h2></div>
lots of code...............
</cfoutput>
</cftextarea>
<br />
<br />
<cfelse>
<cftextarea name="custom_report" richtext="true" value="#benchInfo.custom_report#" width="1000" height="600"></cftextarea><br /><br />
</cfif>
<cfinput type="hidden" name="benchid" value="#attributes.benchid#" />
<cfinput type="submit" value="Submit" name="Submit" />
</cfform>
The submit button takes them to the action page that creates the cfdocument;
<cfparam name="doc_title" default = "#replace(benchInfo.title, " ", "_", "all")#" />
<cfset doc_title = #replace(benchInfo.title, " ", "_", "all")# />
<cfset custom_report2 = "#replace(form.custom_report, "<--- This is a page break --->", "|", "all")#">
<cfinvoke component="cfc.updates" method="updSalBenchCustomReport" sb_id="#attributes.benchID#" custom_report="#custom_report2#" />
<cfset infoReplaceBegin = "<!-- Info -->">
<cfset infoReplaceEnd = "<!-- End Info -->">
<cfdocument format="pdf" filename="#request.Controlpath#salarybenchmarking\reports\#benchid#\#doc_title#_client.pdf" overwrite="yes"
marginbottom=".5">
<cfdocumentitem
type = "footer">
<cfoutput>
<div style="float:left; text-align:left; border-top:1px solid ##910062; width:100%; padding-top:5px; horizontal-align:top;">
<img src="#request.controlurl#images/Logo_small.jpg" />
<span style="padding-left:215px; line-height:12px;">www.Tt.com</span>
<span style="padding-left:225px; font-size:12px;">Page #cfdocument.currentpagenumber# of #cfdocument.totalpagecount#</span>
</div>
</cfoutput>
</cfdocumentitem>
<cfoutput>
<cfset counter = 0>
<cfloop list="#custom_report2#" delimiters="|" index="x">
<cfset counter = counter + 1>
<cfif counter eq 1>
<cfset infoBegin = findnocase(infoReplaceBegin,x)>
<cfset infoEnd = findnocase(infoReplaceEnd,x)>
<cfif val(infoBegin) and val(infoEnd) and (val(infoEnd) gt val(infoBegin))>
<cfset stringCount = evaluate((infoend - infobegin)+len(infoReplaceEnd))>
<cfset tempString = mid(x,infoBegin,stringCount)>
<cfset x = replacenocase(x, tempString, '')>
</cfif>
</cfif>
#x#
<!--- Check to see if it's not the last delimiter --->
<cfif counter lt evaluate(listlen(custom_report2,"|")-1)>
<cfdocumentitem type="pagebreak"></cfdocumentitem>
</cfif>
</cfloop>
</cfoutput>
</cfdocument>
<cfset compReplaceBegin = "<!-- Companyname -->">
<cfset compReplaceEnd = "<!-- End Companyname -->">
<cfdocument format="pdf" filename="#request.Controlpath#salarybenchmarking\reports\#benchid#\#doc_title#_participant.pdf" overwrite="yes" marginbottom="0">
<cfoutput>
<cfloop list="#custom_report2#" delimiters="|" index="x">
<cfset compBegin = findnocase(compReplaceBegin,x)>
<cfset compEnd = findnocase(compReplaceEnd,x)>
<cfif val(compBegin) and val(compEnd) and (val(compEnd) gt val(compBegin))>
<cfset stringCount = evaluate((compend - compbegin)+len(compReplaceEnd))>
<cfset tempString = mid(x,compBegin,stringCount)>
<cfset x = replacenocase(x, tempString, '')>
</cfif>
#x#
<div style="float:left; position:absolute; top:925px; text-align:center; border-top:1px solid ##910062; width:100%; padding-top:5px;">
<div style="float:left; "><img src="#request.controlurl#images/Logo_small.jpg" /></div>
<div style="text-align:center; float:left; width:80%;">www.Tt.com</div>
<div style="float:right; position:absolute; width:100%; text-align:right; font-size:10px; padding-top:10px;">Page 1 of 1</div>
</div>
<cfbreak>
</cfloop>
</cfoutput>
</cfdocument>
<cfoutput>
<br />
View Client PDF<br />
<br />
View Participant PDF<br />
<br />
<a href="#request.controlURL#salarybenchmarking/index.cfm?fa=view&benchID=#attributes.benchID#" >Return to Benchmark Details</a><br />
<br />
Salary Benchmarking Home<br />
<br />
</cfoutput>
The problem comes in when a little too much data is entered an automatic page break is created. Sometimes the user has to spend time abbreviating their notes to make it fit on the page. I was thinking I could allow them to change the font/size and save that info. Then they can re-create the PDF and see if it "fits". I can see where a global font/size might be a little tricky. I need some type of dialog box to allow the user to make a global font selection.
<cfdocument scale="xx">
zooms the whole pdf

Coldfusion : How to include HTML table headers on new page when using cfdocument?

I have a table on a page with data generated from a query. This makes it unpredictable how many rows will be generated.
When using cfdocument to output the page as a PDF the table is often cut in two on the page break.
Is there any easy way to include the table labels on the new page for the purpose of clarity?
I've had to work with cfdocument quite a bit and making it usable in certain situations can be a real bear.
I believe the answer to your question can be found on this page since you know how many records will be on each page (static row height):
COLDFUSION: cfdocument and forcing a pagebreak
Here are some other questions I've posted and worked through concerning cfdocument, hope they help.
scale PDF to single page
cfdocument prevent page breaks mid-row
CFDocument still cutting off the tops of text on some pages
try this approach, I have used it
<cfset amount="6" />
<cfdocument
format="pdf"
unit="cm"
pageType="A4"
filename="#path##name#.pdf">
<cfoutput>
<cfloop from="1" to="#amount#" index="i">
<cfset filename = "#name#_#i#" />
<cfimage
action="convert"
destination="#path#codes/#filename#.jpg"
source="#path#codes/#filename#.png" />
<img src="file://#path#codes/#filename#.jpg" style="width: 3.58cm; margin: 0 0.2cm 0.5cm;">
</cfloop>
</cfoutput>
Just adding some things that DON'T work (in CF10, which i think uses the same CFdoc renderer as CF8 & CF9):
adding content after the header element with css:after (CFdocument doesn't support css3)
thead { display: table-header-group; } (not supported)
using javascript within the table output to add a header row dynamically (the pdf renderer doesn't execute js)
testing #cfdocument.currentpagenumber# in the cfdocument body (that variable seems only to exist in the header and footer)
adding a in the (soundsOfTheDot answered his other question saying that this worked, but in my tests the renderer seems to close the table at the end of each page then re-open it)
adding a table in the with a test like to insert it on all pages after the first one (this almost does the job, if you can hard-code your column widths so the two tables line up and ensure there is no gap between this faux header and the actual table)
I hope that saves some hours.
My PDF happened to fit 21 rows per page, so I made sure the current row MODULO 21 equaled 0. Notice I start with a new table each page, so I put the new <table> along with only a <thead> inside the <cfif> after using the closing tags of </tbody> and </table> for the previous page's table and the pagebreak. Then I follow it with the <tbody>, and voila, it works like a charm. I also added a nice footer to the PDF just for funsies.
<cfquery name="getDeletedBarcodes" datasource="#application.dsn#">
SELECT * FROM deletedRecords
</cfquery>
<cfdocument filename="reports/DeletedBarcodes.pdf" format="PDF" overwrite="true">
<cfif getDeletedBarcodes.RecordCount NEQ 0>
<h2 align="center" style="text-decoration: underline; font-weight: bold">Deleted Barcode Records</h2>
<table class="deletedBarcodesTable" border="1" style="margin-top: 10px" rules="rows">
<thead>
<tr>
<th>Barcode</th>
<th>Building</th>
<th>Room</th>
<th>Location</th>
<th>Shelf</th>
<th>Inventoried</th>
<th>Deleter Name</th>
<th>Time Deleted</th>
<th>Reason Deleted</th>
</tr>
</thead>
<cfelse>
<p>There are no records to show that have deleted barcodes.</p>
</cfif>
<cfloop query="getDeletedBarcodes">
<cfoutput>
<cfif getDeletedBarcodes.currentRow MOD 21 EQ 0>
</tbody></table>
<cfdocumentitem type="pagebreak" />
<table class="deletedBarcodesTable" border="1" style="margin-top: 10px" rules="rows">
<thead>
<tr>
<th>Barcode</th>
<th>Building</th>
<th>Room</th>
<th>Location</th>
<th>Shelf</th>
<th>Inventoried</th>
<th>Deleter Name</th>
<th>Time Deleted</th>
<th>Reason Deleted</th>
</tr>
</thead>
<tbody>
</cfif>
<tr>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "Barcode") OR NOT len(Barcode)><strong style="color: red">N/A</strong><cfelse>#Barcode#</cfif></td>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "Building") OR NOT len(Building)><strong style="color: red">N/A</strong><cfelse>#Building#</cfif></td>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "Room") OR NOT len(Room)><strong style="color: red">N/A</strong><cfelse>#Room#</cfif></td>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "Location") OR NOT len(Location)><strong style="color: red">N/A</strong><cfelse>#Location#</cfif></td>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "Shelf") OR NOT len(Shelf)><strong style="color: red">N/A</strong><cfelse>#Shelf#</cfif></td>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "Inventoried") OR NOT len(Inventoried)><strong style="color: red">N/A</strong><cfelse>#LEFT(Inventoried, 10)#</cfif></td>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "DeleterName") OR NOT len(DeleterName)><strong style="color: red">N/A</strong><cfelse>#DeleterName#</cfif></td>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "TimeDeleted") OR NOT len(TimeDeleted)><strong style="color: red">N/A</strong><cfelse>#TimeDeleted#</cfif></td>
<td align="center"><cfif NOT StructKeyExists(getDeletedBarcodes, "ReasonDeleted") OR NOT len(ReasonDeleted)><strong style="color: red">N/A</strong><cfelse>#ReasonDeleted#</cfif></td>
</tr>
</cfoutput>
</cfloop>
<cfdocumentitem type="footer">
<cfoutput>
<div style="border-top: 5px solid black; border-top-width: 100vw">
<span style="left: 0; float: left">#DateFormat(Now(), "full")#</span>
<span style="right: 0; float: right">Page #cfdocument.currentpagenumber# of #cfdocument.totalpagecount#</span>
</div>
</cfoutput>
</cfdocumentitem>
</cfdocument>

Force a page break and including headers when using cfdocument?

I'm generating a <table> and converting it to PDF using <cfdocument>. I would like to include the table header on the new page when it runs over. This is around every 30th line.
Here is my current code. The <cfif> is supposed to force a break at every new line. However, all it seems to do is create 4 blank pages with the content at the bottom, formatted the same as it was before
<cfloop query="One">
<cfif not(One.currentrow MOD 30)>
<cfdocumentitem type="pagebreak" />
<th>Contact Name</th>
</cfif>
<cfoutput>
#One.contactName#
</cfoutput>
Fixed. Here is what I used to get my header on every page. Further note, if you need to adjust the document header size, then include margintop="2.2" in your main tag and adjust to taste.
<cfdocumentitem type="header" evalAtPrint="true" >
<td>Contact Name</td>
</cfdocumentitem>
Try This: This is the solution that i got.
<cfloop query="get_list">
<!---7 row each page--->
<cfset mode = get_list.currentrow mod 7>
<cfif mode eq 1>
<thead>
<tr>
<td>table header</td>
</tr>
</thead>
</cfif>
<tbody>
<tr>
<td>data loop here</td>
</tr>
<tr>
<td>
<cfif mode eq 0>
<cfdocumentitem type="pagebreak">
</cfdocumentitem>
</cfif>
</td>
</tr>
</tbody>
</cfloop>
</table>