ColdFusion: how to populate livecycle pdf section dynamically using query data - coldfusion

I have a template PDF that has a section that will be laid out like a table. The data will come from a query. So this table will be dynamic, number of rows unknown.
How do I accomplish this using ColdFusion? Is it a combination of creating a template using LiveCycle and creating this section so it is dynamic and then using CFPDF to populate it.
Right now I'm using to populate static fields.
<cfpdfform source="Template.pdf"
destination="Template2.pdf" action="populate">
<cfpdfsubform name="form1">
<cfpdfformparam name="pdf_controlNum" value="123">
<cfpdfformparam name="pdf_ReportDate" value="05/01/2012">
</cfpdfsubform>
</cfpdfform>

I found the solution. It was in this forum:
http://www.experts-exchange.com/Software/Server_Software/Web_Servers/ColdFusion/Q_26528588.html
At bottom of thread was this:
2 key points
1. in cf you need to set overwritedata=”yes” in cfpdfform
2. the pdf needs to be a dynamic pdf.
hope this helps others. I don't have a how to blog but if you know of one just let me know. Very handy indeed.
<cfpdfsubform name="details">
<cfpdfsubform name="Table1">
<cfloop from="1" to="#getClientOrderDetails.recordCount#" index="i">
<cfpdfsubform name="Row1" index = "#i#">
<cfpdfformparam name="pdfDescription" value="#getClientOrderDetails.ItemDescription[i]#">
<cfpdfformparam name="pdfItemQuantity" value="#getClientOrderDetails.ItemQuantity[i]#">
<cfpdfformparam name="pdfItemUnitPrice" value="#getClientOrderDetails.ItemUnitPrice[i]#">
</cfpdfsubform>
</cfloop>
</cfpdfsubform>
</cfpdfsubform>

Did you just want to create a PDF File? If so you also have to call in the style sheet after the cfdocument
<cfdocument
format="pdf"
filename = "pdf_file_path\#pdf_controlNum#_#pdf_ReportDate#.pdf"
overwrite = "yes"
marginBottom = ".2"
marginLeft = ".4"
marginRight = ".4"
marginTop = ".2">
<style type="text/css">#import "pdf.css";</style>
QUERY RESULTS TABLES AND CODING HERE ETC
</cfdocument>

Related

Can i remove Pagination from external site with cfhttp

I am fetching one website results in my website and if there are any much more records, the pagination is also coming along with it, so it is displaying pagination and records
this is more than a question rather than before i make any try and i do not know where to start
is this possible, can i make infinite pagination of the results through some client side or server side, let me know please thanks
Pagination look like this in the cfhttp.filecontent as:
<TD align="right" width="100"><font class="MainBody">Pages: << 1 2 >> </FONT></TD>
This should work for you. It searches for a TD tag followed by a FONT tag, followed by Pages.. and then searches to the first closing TD.
The result is stored in newfilecontent.
<cfset newfilecontent = REReplaceNoCase(cfhttp.filecontent,"<td.*?><font.*?>Pages.*?<\/td>","","ALL")>
With a more detailed question, what you need is basically a rudimentary spider.
This is only designed to work from the first page of results onward. You can't target this at say, page 3, and get page 2 and page 1's.
<cfhttp...> <!--- initial cfhttp --->
<cfset buildContents = ArrayNew(1)>
<cfset buildContents[1] = ReReplaceNoCase(cfHttp.fileContent,".*<body.*?>(.*)</body>.*","\1","ALL")>
<!--- Quick regex to parse the contents of the body tag out of the cfhttp --->
<cfloop condition="#ReFindNoCase("(http[^""]*?pagenum=\d+)(?="">>>)",currentContent)# gt 0">
<cfset GetNextPage = ReMatchNoCase("(http[^""]*?pagenum=\d+)(?="">>>)",currentContents)>
<cfhttp url="#GetNextPage[1]#"... result="inLoop">
<cfset currentContents = ReReplaceNoCase(inLoop.filecontent,".*<body.*?>(.*)</body>.*","\1","ALL")>
<cfset ArrayAppend(buildContents,REReplaceNoCase(currentContents,"<td.*?><font.*?>Pages.*?<\/td>","","ALL"))>
<cfif ArrayLen(buildContents) gt 10>
<!--- This code is untested, so this is a safety that you can remove or modify. If BuildContents has more than ten elements, it stops the looping. You can remove this cfif or maybe raise the number as a safety net.--->
<cfbreak>
</cfif>
</cfloop>
<cfdump var="#buildContents#">

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

Create Spreadsheet from Multiple Queries

In try to create a spreadsheet that is generated from multiple queries, the following code only generates one row of data and not the entire spreadsheet:
<cfset filenametouse = 'Usage_Report' />
<cfset theDir = GetDirectoryFromPath(GetCurrentTemplatePath()) />
<cfset theFile = theDir & filenametouse & ".xls" />
<cflock name="fileActionSentItems" type="exclusive" timeout="30" throwontimeout="true">
<cfset SpreadsheetObj = spreadsheetNew()>
<cfset fcol = {}>
<cfset fcol.dataformat = "#">
<cfset SpreadsheetAddRow(SpreadsheetObj, "Part Number, Description, Allocated, On Hand, Pending Receipt, Job Count, Qty Needed, Qty Issued, Order Count, Qty Ordered, Qty Shipped")>
<cfoutput>
<cfset SpreadsheetAddRows(SpreadsheetObj,"#getParts.partnum#, #getParts.partdescription#, #getParts.allocated#, #getParts.onhand#, #receiptdata.recqty#, #jobdata.JobCount#, #jobdata.QtyNeeded#, #jobdata.qtySent#, #orderdata.ordercount#, #orderdata.ordered#, #orderdata.shipqty#")>
</cfoutput>
<cfset SpreadsheetFormatColumn(SpreadsheetObj,fcol,11)>
<cfspreadsheet action="write" filename="#theFile#" name="SpreadsheetObj" sheetname="Sheet1" overwrite="true" />
</cflock>
The spreadsheetAddRows isn't creating the data to populate the rows. What am I not doing correctly?
You need to pass in the query object instead of a single row of data.
<cfset SpreadsheetAddRows(SpreadsheetObj, getParts) >
As an aside, you probably do not need to lock that whole section. If the lock is intended to prevent concurrent file access, you only need to lock the code writing the sheet to disk. (Depending on your needs, you might also use a more granular name. But that is just a guess.)
You're not looping through the query to assign more than one row. Because you don't specify what position the values should come from, they're being assigned from the first record in each query.
Create another query containing everything you want in the spreadsheet with queryNew()
<cfset newQuery = queryNew("partNo,desc,allocated,onHand,rendingReceipt,jobCount,qtyNeeded,qtyIssued,orderCount,qtyOrdered,qtyShipped","varchar,varchar,varchar,varchar,varchar,varchar,integer,integer,integer,integer,integer,integer,integer,integer") />
... etc, assigning cells as you go. When you have a complete query object, then you can add that to spreadsheetAddRows(spreadsheetObj,newQuery) />
If you find the spreadsheet creation to be too slow, you may want to check out POI Utility at http://www.bennadel.com/projects/poi-utility.htm Not as configurable as the spreadsheet options, but faster for some work loads.

cffeed function: show just most recent post?

We have a function to pull RSS feeds and display the post on a ColdFusion page using this code:
<cfset rssUrl = "rss1">
<cffeed action="read" source="#rssUrl#" query="fitness" properties="info">
<cfset rssUrl2 = "rss2">
<cffeed action="read" source="#rssUrl2#" query="nutrition" properties="info">
<cfif #fitness.PUBLISHEDDATE# gt #nutrition.PUBLISHEDDATE#>
<cfset entries="fitness">
<cfelse>
<cfset entries="nutrition">
</cfif>
Output done via:
<cfoutput query="#entries#">
Problem is, the RSS feed has several posts and we only want to show one. Any thoughts on how to get it to pull and display only the most recent post? (We want the feed to have multiple posts, so right now our non ideal solution is to set maximum posts per feed to 1)
cfoutput/query=".." will go over an entire query. If you only want to do the first row, use:
<cfoutput>
Title from row 1: #somequery.title[1]#
</cfoutput>
Basically - array notation on the column. Make sense?
There's nothing wrong with Ray's answer, but here are some other options.
<cfoutput query="#entries#" maxrows="1">
Offers the least disruption to your existing code and, should you decide to change the number of rows displayed (like, via a user setting) it's an easy change.
OR
If you copy the query object rather than the query name (which isn't actually a copy but a copy by reference)
<cfset entries = fitness>
instead of
<cfset entries = "fitness">
you can do this
<cfoutput>
#entries.columnName1#
#entries.columnName2#
<!--- etc. --->
</cfoutput>
which will, by default, display only the first row of the query.

cfml, database and a multilingual website

I have a database that has four columns id,languageid,name,text
Depending on the users' default language, I create a query that has all the texts for the set language (where languageid=#user.defaultlanguageid#)
What's the easiest way of retrieving these when it comes to displaying the required string.
Seems like creating a subquery every time is a bit much work.
Is creating a function the best way to go?
You could just have a single query that populates a struct (perhaps an application-level struct) - something like this:
<cfif not IsDefined("application.langMap")>
<cfquery name="langNames" datasource="...">SELECT * from langTable</cfquery>
<cfset application.langMap = {}>
<cfloop query="langNames">
<cfif not StructKeyExists(application.langMap, languageid)>
<cfset application.langMap[languageid] = {}>
</cfif>
<cfset application.langMap[languageid][name] = text>
</cfloop>
</cfif>
And then as you need the particular string within the display:
#application.langMap[mylanguageid][name]#