Working on open source projects is fun and educational.
I've always enjoyed molding reality to my will, as it were-- creating stuff and whatnot.
I've got mad skills at tweaking other peoples work tho, which means most of my "creations" are just mixes of various other people's work.
Pure creation is somewhat hard to organize, for me, but dirty "make it so" type stuff... no problem.
Anyways, on with the story!
For this example, we'll use my foray into CFEclipse land.
I've been there a few times before, to try to impose my will on reality, as I mentioned earlier.
In my previous visits, I was interested in adding "occurrence marking" (OM) to the editor.
I like how in other editors, when you select a word, all the occurrences of the word are selected. I wanted to add this to CFE.
So I went out, and was like, "hmmm... the java editor has OM, why not see how it does it?" so I browsed through the sources... found the spot, and was like "we are not doing anything like this in CFE". I think. It's been a while.
Anyways, it wouldn't easily jive with what we already had, so I searched through the eclipse mailing lists, or something, and found an example that was using the same classes we were using.
From there it was just fitting it in the right spot.
I think. It's been a while. Generally, that's how it goes, tho.
Anywho, let's get a bit more specific. A little fresher...
After journeying through the sources for CFE, it became apparent that it had been written a while ago. There was a lot of code that is now baked into eclipse, that was having to be maintained, this whole time. Not to say things were stale...
Looked like many of my projects, actually. Artifacts around, some stuff using newer things, some older, etc.. After as long as 10 years in some cases...
Every once in a while you've got to do some type of spring cleaning or something, and blow the dust out, re-think stuff, etc..
I started thinking it might be time to blow the dust out of CFE, so to speak.
So I started looking towards Eclipse itself-- I've been dicking with it long enough, I could probably just hack on JTD by now, and make a killer CF editor. But ouch! The maintenance. I'd be using a lot of internal stuff, that would be changing and whatnot... eh...
So next I'm like "well, an API that ties in with the core eclipse stuff wouldn't be too bad..." and so I looked at Aptana. There are some good demos, a wiki and whatnot, for building editors... I like that. But I don't like that SFTP costs money.
If I were out to make a buck, (which I am, really) it is a good option, as the framework for "pay for more" is already set up.
Money aside, it's a good pick, because it's got a decent community, and *documentation*.
Now, I like documentation as much as the next guy, but honestly, I'm a source-er. I find it almost easier to look at the code and see what's possible than reading documentation at times (the code is what's there, the documentation isn't quite real-- besides the auto-generated stuff, of course (it's always in sync)).
Still, walk-thrus and whatnot make it easier for people to get up and running, which is a big plus for Aptana. Plus, it's geared toward integrating CSS and JS and whatnot...
But there's just something that made me not want to go that direction. I don't know if it's my fear of making money, or what. Ha ha. Really it's the not-quite-open idea... I don't mind paying for support, or service, if I need it, or sponsoring features and whatnot... but I don't like paying license fees.
Now, this means making millions of dollars will be hard for me, if all I sell is work, vs. cashing in on existing work, so to speak.
Possibly. I'm thinking I can make plenty, anyways, but it *is* a different approach...
I may end up doing license type stuff anyways, ya know. I won't feel evil, if I do. Whatever's clever, I figure.
But anyways, I've also been watching the Eclipse based tools for doing web work-- at first, it was heavily geared towards pure J2EE java type stuff... good CSS and HTML editing, Hibernate/JDO stuff, great XML editing, but no javascript editing, no WYSIWYG html/css, and lots of it was internal (meaning not a hard API, and things were subject to change).
It was just building steam tho, which I was aware of, and impatient for. In the meantime I used various plugins that did javascript editing, say (don't need wysiwyg html much these days). IBM actually contributed some stuff initially, to help keep the ball rolling... just a note...
Anyways, the Eclipse stuff like WTP has really been taking off... there's a WYSIWYG html editor now, and more of the API is stable-ish... and /man/ the javascript editor kicks ass... and enter the Dynamic Language Toolkit.
DLTK I'd been watching also. I've been curious, seeing some duplication of work (WTP is doing a java editor, ATP was doing one, DLTK has one-- meanwhile, I'm loving JSEditor...) as to which horse to ride... sometimes waiting ROCKS, because it looks like the horses are forming a team, which, WOOHOO! we all get further faster.
Ennyhoo, after a recent jaunt over to DLTK, and seeing not the stagnation that I was fearing, but life, LIFE!, I started thinking... this feels right. Better than Aptana, although Aptana is fine-- I feel like Aptana is really someone else's tho, and Eclipse is everyone's (with a big business partner, IBM :). Just a different feel.
Plus, I'm loving all the crap that comes with these "platform tool" projects like WST/WTP, Data Tools, Testing and Performance... they all sorta plug into one another, and make for a uniform and powerful environment for working on stuff. More uniform and powerful by the day.
Anyways, since currently a JDT-ish CF IDE is out, the next best thing, in my mind, is an API designed for dynamic language editing. DLTK is that API.
There's also the bonus that any work on the actual DLTK code will benefit other languages as well, like Python or Ruby, or PHP (depending on what happens with PHP, I reckon-- still a lot of divergence there... eh.). Something we won't get out of a pure JDT-like CF IDE.
Eh. A lot of working with open source is making decisions like this. What project to go with/contribute to, etc.. Will it last? Is it the best? We don't like the beta-max/vhs type deals, but they happen.
And then there's feelings. You've got to feel something for the project. I loved FCKEditor from the beginning, just because. Not just the ass-kicking-ness of it, but the attitude just felt good.
I honestly didn't care about community support, if it would have staying power, or any of that, it was just fun to contribute.
Heh... actually, that's pretty much the way I've gone about it... maybe I'll reverse what I just said, and say, who cares if the project has a vibrant community (the good ones, and the ones you're drawn too will, anyways) or will be the de-facto in 5 years... if working on it seems like fun, just do it.
Eh. I guess it's a fine time to tie up this long ass initial post with a bit more meat.
When I wanted to add key-binding to Subclipse, an SVN tool for eclipse, I saw that the CVS plugin could to it (Probably the best implementation of a CVS client ever).
So I looked through the CVS plugin sources, and found where/how they were doing it. "Hmmm", I think. -- they've done some stuff that makes doing other stuff (like key-binding) pretty easy. It also means a direct cut and paste (for all intents and purposes) won't cut it.
Oh well, I'll see if I can take the bits that do what I want, and git'em into Subclipse. Long story short, I did.
I learned quite a bit, too. I'll close this first installment of [whatever this is] with a link to the original Subclipse enhancement ticket, and the dialog between myself and a great developer, Mark Phippard.
It's a good example of a noob trying to contribute.
http://subclipse.tigris.org/issues/show_bug.cgi?id=394
Some related emails:
http://svn.haxx.se/subdev/archive-2005-11/0007.shtml
Sunday, April 20, 2008
Saturday, January 05, 2008
Improvement... Direction...
So... for Dan Dubs, I'm gonna just bust some entries, (as in bust a move (but not the movie)) and see what happens.
At first I was like, "what should I write about?" you know? Whether or not to put punctuation inside sentences in parenthesis? "Naw..."
I figured I'd talked some on the CFEclipse (CFE) users list about where I thought we should look for the future of CFE, so why not do one on that?
I was also thinking about, well, I've got a ton of odd tidbits of code lying around-- as I see this blog entry getting saved automagically, I'm like "hey, I once got the little auto-saving ajax plugin for FCKEditor working with some stuff, maybe I should share that, seeing as FCK's in cf8"... it's not rocket science, and you can do most of it by reading instructions, (this is in reference to most of my stuff, really) but I figure, you know, I should at least take a stab at distilling (not sure that's the right word) what I know- hmm, condensing? Bah. anyways -- do it to save some other people some time, maybe- or, probably about the only good- give others ideas.
I try to follow standards and whatnot, but I'm (obviously) a bit, um, fast paced? Lazy? both fit. What I'm getting at tho, is I wouldn't want people to look at my stuff, and think "that's how you should do it" -- "that's one way to do it, maybe not the best- hell, maybe 'bad', even. Heh." yup, that's more like it. I talk a lot about standards, and organization... design patterns and whatnot, so I should really be a bit less sloppy.
Which I know, and I keep putting off sharing stuff because it's not perfect (or whatever- I always see things I could make better, etc., and I'm like... "I'll do this first, then put it up somewhere") and besides that, I've got a job that I'm devoting mad time to, so I can let it go feeling good about the future of the work we've done. I'm a [former, yay!] lone coder, but it's been a team effort for these applications. But I digress.
I wanna improve stuff.
For CFE, I think we should think about joining up with the WTP stuff, or the Dynamic Language Toolkit stuff (note to me: add links later).
We would instantly get some good benefits -- html, css, perhaps a integrated deal, for code completions and whatnot, or better mylyn integration, things like code folding and whatnot a little better abstracted than the current incarnation of CFE, I'd wager... I love what the java editor can do, like the auto-refactoring (you change a class name, it updates references to the class everywhere, etc.- slick stuff!) and whatnot, and I'd love to see CFE there. Or a little closer.
I think. I'm still working through the moral implications of contributing to a closed language. LOL. Not. ... Well, I'm not letting it stop me, although, seriously, I do think about it. I think about a lot. Think think think.
At least if we stated using some of those other open source projects, and we make ours better, it will be making theirs better as well, which turns me on. Yes, my nipples are hard just thinking about it.
For direction, perhaps I'll post a blog entry, with like some of the things I could blog about. The SVN stuff I've been working on (a repository browser and editor, using some dojo js and FCK (of course! Auto-saving y todo ;] ), or the StorageService concept I landed on for doing session/application/ORM/File(sorta)/And Soon SVN storage (it's kinda cool, I guess, but I think it's probably "wrong" as far as patterns go-- eh). Perhaps the (probably overkill) AOP access control stuff? The half-assed (yet it sorta worked) request streaming, "pushlet" deal I did off the original AOP logging example code (that I need to send to another Dan)?
Heh. I guess I sorta started hammering it out right here. That'll work.
I'm listening to the Violent Femmes at this precise moment (for me, of course. For you, hell, could be like hours ago, or maybe years... eons? Let's hope we're around that long...)
Fuck. I think I'm going to be cursing a little in these blog entries. Yup. That way it won't look weird when I eventually pull everything into the /real/ blog I'm gonna use, when I'm finished perfecting it, probably around half past a monkey's ass, quarter to a pimple.
I'm finished here, besides maybe adding links later, I think. Time to use my laser-like conscience for another blog target. Or maybe I'll just read some more email. Or spend a second on that livespeller for FCK... hmmm... adding some more keybindings to subclipse? Done with my work quota hrs already...
I'm getting organized, see.
Or something like that. Running disorganized, perhaps, but better than sitting and thinking (you know what I mean).
At first I was like, "what should I write about?" you know? Whether or not to put punctuation inside sentences in parenthesis? "Naw..."
I figured I'd talked some on the CFEclipse (CFE) users list about where I thought we should look for the future of CFE, so why not do one on that?
I was also thinking about, well, I've got a ton of odd tidbits of code lying around-- as I see this blog entry getting saved automagically, I'm like "hey, I once got the little auto-saving ajax plugin for FCKEditor working with some stuff, maybe I should share that, seeing as FCK's in cf8"... it's not rocket science, and you can do most of it by reading instructions, (this is in reference to most of my stuff, really) but I figure, you know, I should at least take a stab at distilling (not sure that's the right word) what I know- hmm, condensing? Bah. anyways -- do it to save some other people some time, maybe- or, probably about the only good- give others ideas.
I try to follow standards and whatnot, but I'm (obviously) a bit, um, fast paced? Lazy? both fit. What I'm getting at tho, is I wouldn't want people to look at my stuff, and think "that's how you should do it" -- "that's one way to do it, maybe not the best- hell, maybe 'bad', even. Heh." yup, that's more like it. I talk a lot about standards, and organization... design patterns and whatnot, so I should really be a bit less sloppy.
Which I know, and I keep putting off sharing stuff because it's not perfect (or whatever- I always see things I could make better, etc., and I'm like... "I'll do this first, then put it up somewhere") and besides that, I've got a job that I'm devoting mad time to, so I can let it go feeling good about the future of the work we've done. I'm a [former, yay!] lone coder, but it's been a team effort for these applications. But I digress.
I wanna improve stuff.
For CFE, I think we should think about joining up with the WTP stuff, or the Dynamic Language Toolkit stuff (note to me: add links later).
We would instantly get some good benefits -- html, css, perhaps a integrated deal, for code completions and whatnot, or better mylyn integration, things like code folding and whatnot a little better abstracted than the current incarnation of CFE, I'd wager... I love what the java editor can do, like the auto-refactoring (you change a class name, it updates references to the class everywhere, etc.- slick stuff!) and whatnot, and I'd love to see CFE there. Or a little closer.
I think. I'm still working through the moral implications of contributing to a closed language. LOL. Not. ... Well, I'm not letting it stop me, although, seriously, I do think about it. I think about a lot. Think think think.
At least if we stated using some of those other open source projects, and we make ours better, it will be making theirs better as well, which turns me on. Yes, my nipples are hard just thinking about it.
For direction, perhaps I'll post a blog entry, with like some of the things I could blog about. The SVN stuff I've been working on (a repository browser and editor, using some dojo js and FCK (of course! Auto-saving y todo ;] ), or the StorageService concept I landed on for doing session/application/ORM/File(sorta)/And Soon SVN storage (it's kinda cool, I guess, but I think it's probably "wrong" as far as patterns go-- eh). Perhaps the (probably overkill) AOP access control stuff? The half-assed (yet it sorta worked) request streaming, "pushlet" deal I did off the original AOP logging example code (that I need to send to another Dan)?
Heh. I guess I sorta started hammering it out right here. That'll work.
I'm listening to the Violent Femmes at this precise moment (for me, of course. For you, hell, could be like hours ago, or maybe years... eons? Let's hope we're around that long...)
Fuck. I think I'm going to be cursing a little in these blog entries. Yup. That way it won't look weird when I eventually pull everything into the /real/ blog I'm gonna use, when I'm finished perfecting it, probably around half past a monkey's ass, quarter to a pimple.
I'm finished here, besides maybe adding links later, I think. Time to use my laser-like conscience for another blog target. Or maybe I'll just read some more email. Or spend a second on that livespeller for FCK... hmmm... adding some more keybindings to subclipse? Done with my work quota hrs already...
I'm getting organized, see.
Or something like that. Running disorganized, perhaps, but better than sitting and thinking (you know what I mean).
Sunday, September 10, 2006
Musing on Dreamweaver and CF
DW is like the Visual Basic for CF. You could code a
whole "coldfusion" site without really needing to know any
CF. Does that make one a CFer? Sure, and that's part
of the aim of CF, actually, but the power that is mixed with
the ease makes for a pretty diverse population, skillz wise.
And the skill groups seem to "clump" sorta, .. eh. Hard to
verbalize that idea...
But anyway it has some kind of effect on the use of things
like CFEclipse or MyEclipse.
Like Dan P says, we don't see much traffic on list about
things like JWS or JSP and whatnot, yet that's a big
chunk of the power of CF, and you know there are plenty
of people doing cool stuff along those lines...
And what about UML tools or j2ee related things and
frameworks and whatnot... guess that's not really
considered "coldfusion"? More sorta "general" or "specific",
with "no real centralized info" or "specialized list-servs and
whatnot".
I think the glass ceiling is switching from "websites" to
"applications". While you're doing "websites", DW is
the bomb. All the nifty tools are really useful, the Visual
editing is essential... since most stuff isn't programmatic,
or stored in a DB, DW plain kicks ass. The best visual
HTML editing tool available, IMHO.
But sooner or later (if you aren't just doing it to sustain
your other habits, as a day job, or whatnot ;) you start
to realize you're spending all your time in the code view.
DW stops being so helpful. You don't have a million files
all over the place anymore... CF and the site users are
doing the content work, not you and DW. You have a
couple of CSS files, and your HTML is pretty plain looking.
When you change stuff, it's the CSS files/CF functions,
not a DW template or library item.
Suddenly you're developing "web applications" instead of
"web sites" (the term website is pretty general, I know).
Unit tests and frameworks start sounding pretty good.
Automated deployment and continuous integration? Sign
me up!
That's where tools like Eclipse come into play. If you're
not doing all that, Dreamweaver is King. It's still good
for times where you need it, but I've found that I dislike
needing it. There is no reason for the markup to be so
convoluted you need to switch to "design" view just to
visualize it.
To sum up, Dreamweaver is a great tool, top notch in
it's field, which is the HTML IDE field.
The bias, is that I think CF is far more than HTML, and
thus, diserves far more than an HTML IDE. I know DW
can do CF, and PHP, etc., I just think it's geared more
toward WYSIWYG/HTML, than programing.
Bah. Other's have blogged better on this topic. I just
wanted to put down some thoughts, as it's cool to see
how one thunk and wrote, looking back. And maybe
someone will have a comment that gives me pause.
Life is cool like that. Kool, even.
whole "coldfusion" site without really needing to know any
CF. Does that make one a CFer? Sure, and that's part
of the aim of CF, actually, but the power that is mixed with
the ease makes for a pretty diverse population, skillz wise.
And the skill groups seem to "clump" sorta, .. eh. Hard to
verbalize that idea...
But anyway it has some kind of effect on the use of things
like CFEclipse or MyEclipse.
Like Dan P says, we don't see much traffic on list about
things like JWS or JSP and whatnot, yet that's a big
chunk of the power of CF, and you know there are plenty
of people doing cool stuff along those lines...
And what about UML tools or j2ee related things and
frameworks and whatnot... guess that's not really
considered "coldfusion"? More sorta "general" or "specific",
with "no real centralized info" or "specialized list-servs and
whatnot".
I think the glass ceiling is switching from "websites" to
"applications". While you're doing "websites", DW is
the bomb. All the nifty tools are really useful, the Visual
editing is essential... since most stuff isn't programmatic,
or stored in a DB, DW plain kicks ass. The best visual
HTML editing tool available, IMHO.
But sooner or later (if you aren't just doing it to sustain
your other habits, as a day job, or whatnot ;) you start
to realize you're spending all your time in the code view.
DW stops being so helpful. You don't have a million files
all over the place anymore... CF and the site users are
doing the content work, not you and DW. You have a
couple of CSS files, and your HTML is pretty plain looking.
When you change stuff, it's the CSS files/CF functions,
not a DW template or library item.
Suddenly you're developing "web applications" instead of
"web sites" (the term website is pretty general, I know).
Unit tests and frameworks start sounding pretty good.
Automated deployment and continuous integration? Sign
me up!
That's where tools like Eclipse come into play. If you're
not doing all that, Dreamweaver is King. It's still good
for times where you need it, but I've found that I dislike
needing it. There is no reason for the markup to be so
convoluted you need to switch to "design" view just to
visualize it.
To sum up, Dreamweaver is a great tool, top notch in
it's field, which is the HTML IDE field.
The bias, is that I think CF is far more than HTML, and
thus, diserves far more than an HTML IDE. I know DW
can do CF, and PHP, etc., I just think it's geared more
toward WYSIWYG/HTML, than programing.
Bah. Other's have blogged better on this topic. I just
wanted to put down some thoughts, as it's cool to see
how one thunk and wrote, looking back. And maybe
someone will have a comment that gives me pause.
Life is cool like that. Kool, even.
Monday, September 04, 2006
Paginated Scaffold List XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="no" />
<xsl:template match="/">
<cfset viewEvent = viewstate.getValue("myself") & viewstate.getValue("xe.view") />
<cfset editEvent = viewstate.getValue("myself") & viewstate.getValue("xe.edit") />
<cfset deleteEvent = viewstate.getValue("myself") & viewstate.getValue("xe.delete") />
<cfparam name="url.maxrows" default="15" />
<cfparam name="url.startrow" default="1" />
<cfset <xsl:value-of select="object/alias"/>Query = viewstate.getValue("<xsl:value-of select="object/alias"/>Query") />
<cfset variables.prvstart = max(1, url.startrow - url.maxrows) />
<cfset variables.nextstart = min(<xsl:value-of select="object/alias"/>Query.recordcount, url.startrow + url.maxrows) />
<cfset variables.end = min( <xsl:value-of select="object/alias"/>Query.recordcount, (url.startrow + url.maxrows) - 1 ) />
<cfoutput>
<div id="breadcrumb"><xsl:value-of select="object/label"/>s / <a href="#editEvent#">Add New <xsl:value-of select="object/label"/></a></div>
</cfoutput>
<br />
<table class="list">
<thead>
<tr>
<cfset displayedColumns = 1 />
<xsl:for-each select="object/properties/property">
<xsl:if test="primarykey = 'false' and relationship='false' and length < 65535">
<cfset displayedColumns = displayedColumns + 1 />
<th><xsl:value-of select="label"/></th>
</xsl:if>
<!--
<xsl:if test="relationship = 'true' and pluralrelationship = 'false' and length < 65535">
<cfset displayedColumns = displayedColumns + 1 />
<th><xsl:value-of select="label"/></th>
</xsl:if>
-->
</xsl:for-each>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<cfif not <xsl:value-of select="object/alias"/>Query.recordcount>
<tr>
<cfoutput><td colspan="#displayedColumns#"><em>No Records</em></td></cfoutput>
</tr>
<cfelseif <xsl:value-of select="object/alias"/>Query.recordcount gt 1>
<cfoutput>
<cfif url.startrow neq 1>
<a href="#viewstate.getValue("myself")&viewstate.getValue("event")#&startrow=#urlEncodedFormat(variables.prvstart, "UTF-8")#">previous #url.maxrows#</a> /
</cfif>
#url.startrow# - #variables.end# of #<xsl:value-of select="object/alias"/>Query.recordcount#
<cfif variables.nextstart lt <xsl:value-of select="object/alias"/>Query.recordcount>
/ <a href="#viewstate.getValue("myself")&viewstate.getValue("event")#&startrow=#urlEncodedFormat(variables.nextstart, "UTF-8")#">next #url.maxrows#</a>
</cfif>
</cfoutput>
</cfif>
<cfoutput query="<xsl:value-of select="object/alias"/>Query" startrow="#url.startrow#" maxrows="#url.maxrows#">
<cfset keyString = "<xsl:for-each select="object/properties/property"><xsl:if test="primarykey = 'true'">&<xsl:value-of select="alias"/>=#urlEncodedFormat(<xsl:value-of select="/object/alias"/>Query.<xsl:value-of select="alias"/>)#</xsl:if></xsl:for-each>" />
<tr <cfif <xsl:value-of select="object/alias"/>Query.currentRow mod 2 eq 0>class="even"</cfif>>
<xsl:for-each select="object/properties/property">
<xsl:if test="primarykey = 'false' and relationship='false' and length < 65535">
<xsl:if test="cfdatatype = 'date'">
<td><a href="#viewEvent##keystring#">#dateFormat(<xsl:value-of select="alias"/>, "m/d/yyyy")# #timeFormat(<xsl:value-of select="alias"/>, "h:mm TT")#</a></td>
</xsl:if>
<xsl:if test="cfdatatype != 'date'">
<td><a href="#viewEvent##keystring#">#htmlEditFormat(<xsl:value-of select="alias"/>)#</a></td>
</xsl:if>
</xsl:if>
<!--
<xsl:if test="relationship = 'true' and pluralrelationship = 'false' and length < 65535">
<xsl:if test="cfdatatype = 'date'">
<td><a href="#viewEvent##keystring#">#dateFormat(<xsl:value-of select="sourceobject"/>_<xsl:value-of select="sourcecolumn"/>, "m/d/yyyy")# #timeFormat(<xsl:value-of select="sourceobject"/>_<xsl:value-of select="sourcecolumn"/>, "h:mm TT")#</a></td>
</xsl:if>
<xsl:if test="cfdatatype != 'date'">
<td><a href="#viewEvent##keystring#">#htmlEditFormat(<xsl:value-of select="sourceobject"/>_<xsl:value-of select="sourcecolumn"/>)#</a></td>
</xsl:if>
</xsl:if>
-->
</xsl:for-each>
<td>
<a href="#editEvent##keystring#">Edit</a>
<a href="##" onclick="if (confirm('Are you sure you want to delete this <xsl:value-of select="/object/label"/>?')) { document.location.replace('#deleteEvent##keystring#') }; return false">Delete</a>
</td>
</tr>
</cfoutput>
</tbody>
</table>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="no" />
<xsl:template match="/">
<cfset viewEvent = viewstate.getValue("myself") & viewstate.getValue("xe.view") />
<cfset editEvent = viewstate.getValue("myself") & viewstate.getValue("xe.edit") />
<cfset deleteEvent = viewstate.getValue("myself") & viewstate.getValue("xe.delete") />
<cfparam name="url.maxrows" default="15" />
<cfparam name="url.startrow" default="1" />
<cfset <xsl:value-of select="object/alias"/>Query = viewstate.getValue("<xsl:value-of select="object/alias"/>Query") />
<cfset variables.prvstart = max(1, url.startrow - url.maxrows) />
<cfset variables.nextstart = min(<xsl:value-of select="object/alias"/>Query.recordcount, url.startrow + url.maxrows) />
<cfset variables.end = min( <xsl:value-of select="object/alias"/>Query.recordcount, (url.startrow + url.maxrows) - 1 ) />
<cfoutput>
<div id="breadcrumb"><xsl:value-of select="object/label"/>s / <a href="#editEvent#">Add New <xsl:value-of select="object/label"/></a></div>
</cfoutput>
<br />
<table class="list">
<thead>
<tr>
<cfset displayedColumns = 1 />
<xsl:for-each select="object/properties/property">
<xsl:if test="primarykey = 'false' and relationship='false' and length < 65535">
<cfset displayedColumns = displayedColumns + 1 />
<th><xsl:value-of select="label"/></th>
</xsl:if>
<!--
<xsl:if test="relationship = 'true' and pluralrelationship = 'false' and length < 65535">
<cfset displayedColumns = displayedColumns + 1 />
<th><xsl:value-of select="label"/></th>
</xsl:if>
-->
</xsl:for-each>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<cfif not <xsl:value-of select="object/alias"/>Query.recordcount>
<tr>
<cfoutput><td colspan="#displayedColumns#"><em>No Records</em></td></cfoutput>
</tr>
<cfelseif <xsl:value-of select="object/alias"/>Query.recordcount gt 1>
<cfoutput>
<cfif url.startrow neq 1>
<a href="#viewstate.getValue("myself")&viewstate.getValue("event")#&startrow=#urlEncodedFormat(variables.prvstart, "UTF-8")#">previous #url.maxrows#</a> /
</cfif>
#url.startrow# - #variables.end# of #<xsl:value-of select="object/alias"/>Query.recordcount#
<cfif variables.nextstart lt <xsl:value-of select="object/alias"/>Query.recordcount>
/ <a href="#viewstate.getValue("myself")&viewstate.getValue("event")#&startrow=#urlEncodedFormat(variables.nextstart, "UTF-8")#">next #url.maxrows#</a>
</cfif>
</cfoutput>
</cfif>
<cfoutput query="<xsl:value-of select="object/alias"/>Query" startrow="#url.startrow#" maxrows="#url.maxrows#">
<cfset keyString = "<xsl:for-each select="object/properties/property"><xsl:if test="primarykey = 'true'">&<xsl:value-of select="alias"/>=#urlEncodedFormat(<xsl:value-of select="/object/alias"/>Query.<xsl:value-of select="alias"/>)#</xsl:if></xsl:for-each>" />
<tr <cfif <xsl:value-of select="object/alias"/>Query.currentRow mod 2 eq 0>class="even"</cfif>>
<xsl:for-each select="object/properties/property">
<xsl:if test="primarykey = 'false' and relationship='false' and length < 65535">
<xsl:if test="cfdatatype = 'date'">
<td><a href="#viewEvent##keystring#">#dateFormat(<xsl:value-of select="alias"/>, "m/d/yyyy")# #timeFormat(<xsl:value-of select="alias"/>, "h:mm TT")#</a></td>
</xsl:if>
<xsl:if test="cfdatatype != 'date'">
<td><a href="#viewEvent##keystring#">#htmlEditFormat(<xsl:value-of select="alias"/>)#</a></td>
</xsl:if>
</xsl:if>
<!--
<xsl:if test="relationship = 'true' and pluralrelationship = 'false' and length < 65535">
<xsl:if test="cfdatatype = 'date'">
<td><a href="#viewEvent##keystring#">#dateFormat(<xsl:value-of select="sourceobject"/>_<xsl:value-of select="sourcecolumn"/>, "m/d/yyyy")# #timeFormat(<xsl:value-of select="sourceobject"/>_<xsl:value-of select="sourcecolumn"/>, "h:mm TT")#</a></td>
</xsl:if>
<xsl:if test="cfdatatype != 'date'">
<td><a href="#viewEvent##keystring#">#htmlEditFormat(<xsl:value-of select="sourceobject"/>_<xsl:value-of select="sourcecolumn"/>)#</a></td>
</xsl:if>
</xsl:if>
-->
</xsl:for-each>
<td>
<a href="#editEvent##keystring#">Edit</a>
<a href="##" onclick="if (confirm('Are you sure you want to delete this <xsl:value-of select="/object/label"/>?')) { document.location.replace('#deleteEvent##keystring#') }; return false">Delete</a>
</td>
</tr>
</cfoutput>
</tbody>
</table>
</xsl:template>
</xsl:stylesheet>
Sunday, August 27, 2006
Creating "real" Excel files using JExcelAPI and ColdFusion
You probably know that most MS products will import HTML files, so long as you change the extension, e.g.: you create a HTML table and save it as a .XLS to have it open right in Excel. Or save the HTML as a .PPT and it will apparently open in PowerPoint. Stuff like that.
Or maybe you've played with the XML importing/exporting functions that are built into the latest versions of the Office line... wow, nifty- but maybe impractical for various reasons. You may need to support older versions of Excel, say, or just don't like the sheer volume of XML data and wankery that's needed to do so.
There is also Apache POI HSSF, which generates true Excel files, and I believe comes bundled with CFMX. A great alternative to the other two methods I've spoken of so far, but a pretty cumbersom API (POI does lots of stuff besides Excel). And I've heard that JExcelApi performs better on large spreadsheets, but I have not done any tests to verify. I think I heard formula handling was easier with JExcel, too... been a while since I checked out HSSF, so who knows.
Well, if you still want to try JExcelApi after checking out the other methods, you'll need to get the jxl.jar file from the project page of jexcelapi.sourceforge.com. Then you'll want to either drop it in your CF class-path, or use a JavaLoader, so CF can use it.
Once you've got that far, (and I can post an example using the javaloader, eventually) you can start making workbooks!
I really should post just a sample of how to do it plain, but I was working, so that sample is long since gone. Instead I've got a cffunction that will take a struct of queries, and generate sheets for each one in an excel workbook, which is then directly piped to the browser (I hate saving the file just to send it out and then delete anyway).
While this is good for people who don't care about the internals, it's not a very helpful learning example, as it uses a query. KISS, is better for explaining. Oh well, maybe later.
This code could be coded bad too... it works, which is generally what I care about, but I don't know if I'm var-ing stuff right or if reusing the same objects is kosher or whatever. Just to put it out there... I'm not a code guru. If it hurts your dog it's not my fault, blah blah blah
Bah. Here it is:
<cffunction name="queriesToXLS" output="false" hint="I create a XLS workbook from a struct of queries">
<cfargument name="inQueries" type="struct" required="true">
<cfscript>
var outStream = createObject("java","java.io.ByteArrayOutputStream").init();
var workbook = createObject("java","jxl.Workbook");
var ws = createObject("java","jxl.WorkbookSettings").init();
var locale=createObject("java","java.util.Locale").init("en","EN");
var labelObj=createObject("java","jxl.write.Label");
var numberObj=createObject("java","jxl.write.Number");
ws.setLocale(locale);
workbook = workbook.createWorkbook(outStream,ws);
for (i = 1; i lte structCount(inQueries); i = i + 1) {
sheetName = structKeyList(inQueries[i]);
sheetQuery = inQueries[i][structKeyList(inQueries[i])];
sheet = workBook.createSheet(sheetname, toString(i-1));
// ouput column headers
for (qCol = 1; qCol lte listLen(sheetQuery.columnlist); qCol = qCol + 1) {
thisLabel = labelObj.init(toString(val(qCol)-1),0,listGetAt(sheetQuery.columnlist,qCol));
sheet.addCell(thisLabel);
}
for (qRow = 1; qRow lte sheetQuery.recordcount; qRow = qRow + 1) {
for (qCol = 1; qCol lte listLen(sheetQuery.columnlist); qCol = qCol + 1) {
thisLabel = labelObj.init(toString(val(qCol)-1),toString(qRow),toString(sheetQuery[listGetAt(sheetQuery.columnlist,qCol)][qRow]));
sheet.addCell(thisLabel);
}
}
}
workbook.write();
outStream.flush();
workbook.close();
return outStream.toByteArray();
</cfscript>
</cffunction>
<cfargument name="inQueries" type="struct" required="true">
<cfscript>
var outStream = createObject("java","java.io.ByteArrayOutputStream").init();
var workbook = createObject("java","jxl.Workbook");
var ws = createObject("java","jxl.WorkbookSettings").init();
var locale=createObject("java","java.util.Locale").init("en","EN");
var labelObj=createObject("java","jxl.write.Label");
var numberObj=createObject("java","jxl.write.Number");
ws.setLocale(locale);
workbook = workbook.createWorkbook(outStream,ws);
for (i = 1; i lte structCount(inQueries); i = i + 1) {
sheetName = structKeyList(inQueries[i]);
sheetQuery = inQueries[i][structKeyList(inQueries[i])];
sheet = workBook.createSheet(sheetname, toString(i-1));
// ouput column headers
for (qCol = 1; qCol lte listLen(sheetQuery.columnlist); qCol = qCol + 1) {
thisLabel = labelObj.init(toString(val(qCol)-1),0,listGetAt(sheetQuery.columnlist,qCol));
sheet.addCell(thisLabel);
}
for (qRow = 1; qRow lte sheetQuery.recordcount; qRow = qRow + 1) {
for (qCol = 1; qCol lte listLen(sheetQuery.columnlist); qCol = qCol + 1) {
thisLabel = labelObj.init(toString(val(qCol)-1),toString(qRow),toString(sheetQuery[listGetAt(sheetQuery.columnlist,qCol)][qRow]));
sheet.addCell(thisLabel);
}
}
}
workbook.write();
outStream.flush();
workbook.close();
return outStream.toByteArray();
</cfscript>
</cffunction>
Then you'd use it like so:
<cfsetting enablecfoutputonly="true">
<cfquery name="getInfo" datasource="#request.thedsn#">
SELECT * FROM folks
</cfquery>
<cfquery name="getInfo2" datasource="#request.thedsn#">
SELECT * FROM peeps
</cfquery>
<cfset workbookSheets = structNew()>
<cfset workbookSheets[1]["Folks"] = getInfo>
<cfset workbookSheets[2]["Peeps"] = getInfo2>
<cfset daXls = queriesToXLS(workbookSheets)>
<cfset request.cvalue = 'attachment;'>
<cfset request.cvalue = request.cvalue & "filename=test.xls">
<cfheader name="Content-Disposition" value="#request.cvalue#">
<cfoutput><cfcontent type="application/msexcel" variable="#daXls#"></cfoutput>
<cfquery name="getInfo" datasource="#request.thedsn#">
SELECT * FROM folks
</cfquery>
<cfquery name="getInfo2" datasource="#request.thedsn#">
SELECT * FROM peeps
</cfquery>
<cfset workbookSheets = structNew()>
<cfset workbookSheets[1]["Folks"] = getInfo>
<cfset workbookSheets[2]["Peeps"] = getInfo2>
<cfset daXls = queriesToXLS(workbookSheets)>
<cfset request.cvalue = 'attachment;'>
<cfset request.cvalue = request.cvalue & "filename=test.xls">
<cfheader name="Content-Disposition" value="#request.cvalue#">
<cfoutput><cfcontent type="application/msexcel" variable="#daXls#"></cfoutput>
And that should work. Sorry for lack of comments, etc. I'm a baaaaad coder!
Subscribe to:
Posts (Atom)