NO MORE CAREER
POLITICIANS!
Get Out Of Our House: Replacing congress with TRUE citizens!
Contact Doug!
Learn About Doug!
View Doug Boude's online resume
updated 11/18/2009

View Doug Boude's profile on LinkedIn
Link to me!

Follow Doug Boude on Twitter
Follow me!

Be Doug's friend on Facebook
Befriend me!
(I promise not to follow you home)
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...
Web Hosting

best web hosting - top web hosting sites, thetop10bestwebhosting.com

Czech your Page Rank!
Check Page Rank of any web site pages instantly:
This free page rank checking tool is powered by Page Rank Checker service
Surf's Up!
Visit Egosurf.org and massage YOUR web ego!
My Score: 9,001
Doug's Books

Read (and recommend)

  • Men are from Mars, Women are from Venus
  • The Wisdom of Crowds: Why the Many Are Smarter Than the Few and How Collective Wisdom Shapes Business, Economies, Societies and Nations
  • Blink: The Power of Thinking Without Thinking
  • Head First Design Patterns
  • Transact-SQL Programming
  • What's So Amazing About Grace?
  • Just So Stories (Rudyard Kipling collection)

Reading

  • Prayer: Does it Make Any Difference?
  • Data Mining (Practical Machine Learning Tools and Techniques)
<< June, 2009 >>
SMTWTFS
123456
78910111213
14151617181920
21222324252627
282930
Search Blog

Recent Comments
Re: Railo 3.1 on Windows Server 2008 and IIS7 - Part 3 of 3 (by Jon at 8/27 2:04 PM)
Re: Hosts File Changes Not Acknowledged on Vista 64 (by Spacy at 8/24 3:46 PM)
Re: THE DAY CFUNITED DIED (by ComboFusion at 8/23 10:50 AM)
Re: My Grandpa (by Tasha at 8/10 4:29 PM)
Re: Just What IS a 'Service Layer', Anyway? (by dougboude at 8/02 10:10 AM)
Re: Just What IS a 'Service Layer', Anyway? (by Isaac at 8/02 2:25 AM)
Re: PayPal IPN Coldfusion CFC (by Soyestudiambre at 7/25 6:12 PM)
Re: PHP vs COLDFUSION (by Tony Garcia at 7/17 11:24 AM)
Re: PHP vs COLDFUSION (by dougboude at 7/14 8:45 AM)
Re: PHP vs COLDFUSION (by Lola LB at 7/14 5:51 AM)
Categories
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

30 June 2009
PHP Export to Excel Snippet

For those PHPers out there who are doing an export to Excel, I thought I'd share the solution I came up with. I realize there are already a gabillion examples out there, but I merged some of the better approaches from a few of them that made it fairly elegant, I think (such as leveraging the implode, array_keys, and array_values functions).

Without further adieux...

<?php
//your code here to create your sql statement...we'll call it $finalSQL
 
//go get the data we need...
$Result=mysql_db_query($DBName,$finalSQL,$Link);
//fetching each row as an array and placing it into a holder array ($aData)
while($row = mysql_fetch_assoc($Result)){
 $aData[] = $row;
}
//feed the final array to our formatting function...
$contents = getExcelData($aData);

$filename = "myExcelFile.xls";

//prepare to give the user a Save/Open dialog...
header ("Content-type: application/octet-stream");
header ("Content-Disposition: attachment; filename=".$filename);

//setting the cache expiration to 30 seconds ahead of current time. an IE 8 issue when opening the data directly in the browser without first saving it to a file
$expiredate = time() + 30;
$expireheader = "Expires: ".gmdate("D, d M Y G:i:s",$expiredate)." GMT";
header ($expireheader);

//output the contents
echo $contents;
exit;
?>

<?php
 function getExcelData($data){
    $retval = "";
    if (is_array($data)  && !empty($data))
    {
     $row = 0;
     foreach(array_values($data) as $_data){
      if (is_array($_data) && !empty($_data))
      {
          if ($row == 0)
          {
              // write the column headers
              $retval = implode("\t",array_keys($_data));
              $retval .= "\n";
          }
           //create a line of values for this row...
              $retval .= implode("\t",array_values($_data));
              $retval .= "\n";
              //increment the row so we don't create headers all over again
              $row++;
       }
     }
    }
  return $retval;
 }
?>

 

 

Posted by dougboude at 1:06 PM | PRINT THIS POST! | Link | 5 comments



Small But Seriously Irritating Export to Excel Issue

Alright boys and girls, here is an issue and its solution that had me going NUTS for a couple of hours. I actually wrote and implemented three DIFFERENT solutions trying to find a way around the problem, only to find out in the end that I kept carrying the true issue with me.

The Scenario

My user clicks a link and a window pops up allowing them to save or open some exported data as an Excel spreadsheet. Of course, it all worked fine on my machine (two of them, actually), but when my boss tried it on his, he got an error. Not cool. Back to the drawing board.

The Challenge

My first attempt (which worked fine for me) was to create a true excel spreadsheet by streaming the data in binary to a file (it's a bit complicated, but cool). Excel 2007 was able to open it just fine, but my boss' older 2003 could not. So, I decided I'd just fall back on the old reliable CSV type file rather than try and troubleshoot the first approach in too much depth. I coded my CSV export and for the life of me could NOT get my Excel to open it without first flashing me with two nasty error messages, paraphrased here:

"The file you are trying to open '[file name here]' is in a different format than specified by the file extension."

"Excel has detected that '[filename here]' is a SYLK file, but cannot load it."

What the heck??? All we're talking about is some text separated by a comma. And Excel doesn't recognize the format??? Content headers are right; file extension is right; Open it up in a text editor and it sure looks fine to me; What's going on?

I reworked the code to use tabs as delimiters; same symptoms.

The Solution

After dicking with it for a couple of hours, comparing known working CSVs with the one I generated, comparing non printable character strings such as line feeds (which is what I suspected the issue to possibly be), I finally figured out that the TRUE problem was (and I grit my teeth in frustration when saying this): the name of the first column in my data.

NEVER allow the first column in your data to be called "ID". AUGH!!!! (had to scream). Apparently, using "ID" is a trigger to Excel that your file contains a symbolic link to another spreadsheet somewhere. I know, I know, for every OTHER type of file that Excel opens it relies on the file's EXTENSION to determine the type; but not in this case.

Moral of the story: NEVER allow the first column in your CSV data to be called "ID".

Lesson learned, I'm now one small step closer to Nirvana.

Posted by dougboude at 12:30 PM | PRINT THIS POST! | Link | 23 comments
26 June 2009
Disappearing IE Popup Window During Save/Open Dialog

okay, I had a major wrestling match today when attempting to allow my users to automatically save or download a dynamically generated Excel spreadsheet, so thought I'd share the details in case it helps someone else save some hair pulling.

The Scenario

You have a page with a link on it. Clicking this link produces a popup window, the code behind it querying a database, writing an excel file to disk, setting the content headers, and then prompting the user to open or save the file.

The Symptoms

In IE (i'm using version 8), your user clicks the link to "Export Data", popup window appears, and then promptly closes without so much as a "how do you do". (in other browsers, such as Chrome and Firefox, everything behaves just like it should; user clicks link, popup appears, user is immediately prompted to either open or save the file)

The Solution

After trying all MANNER of values for headers, it turns out the magic combo for making it work (in my case, anyway) had two parts to it:

1. DO cache the content. This is accomplished by making sure you DO NOT have a "Pragma: no-cache" header, and including a header like this: Expires: Thu, 01 Dec 2010 16:00:00 GMT (or any other future date...perhaps you could automatically calculate it to be one minute in the future or something). Seems that IE, if you have said NOT to cache content, can't find the file by the time it gets to the dialog because it already uncached it. Strange behavior, but true.

2. Check your browser settings to ensure that you have "Automatic prompting for file downloads" ENABLED. By default it is DISABLED. Here's a screenshot of that setting to help you locate it:

changing automatic download settings in IE 8

After I did those two things, my download link behaved as it did in the other browsers I tested.

Just for clarification, here are the headers and values I ended up with (this is PHP code, so just deal with it):

header ("Content-type: application/vnd.ms-excel");
header ("Content-Disposition: attachment; filename=".$tmpfilename);
header ("Expires: Thu, 01 Dec 2010 16:00:00 GMT");

Okay, that's it. Hope it helps someone else save some time.

Doug out

 

 

Posted by dougboude at 5:23 PM | PRINT THIS POST! | Link | 2 comments
Buying a New Home in San Antonio
My Personal Experience

My wife and I have recently been involved in the search for and procurement of a new home. It started one Saturday this past April when we were driving down the hiway and on a whim decided to stop in at the Centex office in a newly developed subdivision, just to "check it out". By Sunday afternoon we had already selected the model and all of the upgrades for our new home, and were embarked upon the journey of having a house built from the ground up.

It's now nearly July. The house is framed, roofed, wired, plumbed, and is on the verge of having the sheet rock installed. The whole experience thus far has had its ups and downs, but the majority have all been "ups", and I attribute this to two people: my realtor (Terri Russo), and the sales person for Centex (Linda Wilkins).

My wife and I didn't know it, but when you are having a home built, you can and should still have a realtor to represent you during all phases. The initial deterrent to doing so is the thought of adding an extra expense to a probably already tight budget, but (at least with Centex), the realtor's fees are paid by the builder! So with that in mind, I called up a long time friend Terri Russo, a realtor with Russo Group here in San Antonio. Terri is a woman of infinite energy and charisma, with such a thorough knowledge of the home buying/building process that she can (and will) easily translate it into terms that a new home buyer can comprehend. She has accompanied my wife and I on almost every meeting we've had with the builder and has been invaluable when it comes to ensuring that no detail is overlooked or goes unexplained. She always answers her phone (even when on vacation visiting family in Chicago), proactively communicates, and is an invaluable resource when it comes to answering questions like, "Hey, know anybody who does new construction inspections? Tiling? Sells appliances? Gives a good massage?" Terri Russo knows at least one person in nearly every profession there is, I'd say, and will never steer you wrong.

Now let me talk about our Centex sales rep, Linda Wilkins. Linda is THE sweetest woman I've ever met (next to my grandma ). She was recommended to me by a co worker who also had a Centex home built, and from the first time I spoke with her on the phone I was immediately set at ease by her gentle voice and absolute desire to simply help us fulfill our home needs. Not for one single moment in all the months now that we have been working with her have I ever felt like I was talking to a sales person. In fact, I would say that the title doesn't even fit her, as she doesn't "sell" anything; she merely educates you on what your options are and then lets you decide. She, like Terri Russo, is always responsive, caring, empathizing, and leaves no doubt in your mind that your concerns are just as much her own. My wife and I...well, I will admit that I think we have been a wee bit more challenging to work with than probably most new home buyers. But even when we were in her office expressing (in a not so controlled manner) an issue we had regarding the trees in our new yard, she never once reacted negatively and only made it a point to relate to our point of view and then get us a speedy and acceptable resolution. Linda Wilkins, you rock! You can contact Linda on her cell at (210) 336-4522 or by email at linda.wilkins@centex.com .

At this point, I'd like to interject just a few things my wife and I have learned that I feel may be useful to anybody reading this who is considering buying a new home.


1. DO get a realtor. If you already know one personally and trust their abilities, by all means have them represent you. If you don't know one personally, then I highly recommend Terri Russo here in San Antonio. Her cell phone number is 210-385-0305, email address is terri@russogroup.com, and her web site is www.russogroup.com.


2. DO have a home inspector lined up. This is very important, because even though Centex does inspect the work along the way, a third party set of professional eyes looking at it again can't hurt. We had an inspector come out just before the foundation was poured to make sure all pipes, spacers, etc. were right. He found a few things that needed corrected, and Centex was more than happy to address it all. We had him come in again just before the sheet rock goes up, and Centex is also addressing everything on that report as well. The final inspection will be just before closing. Having these inspection reports will also make your home more appealing when it comes time to sell, because the new buyer will know for certain that there were no defects allowed to slip through the cracks.


3. DO take lots of pictures throughout the entire process. Again, this will help potential buyers to feel much more at ease about the house itself, and it will provide good references later on as to where cables are, pipes, etc.


4. DO get as many upgrades as your budget will allow. Remember, the home is an investment and, unless you just plan on NEVER selling it, you'll want to try and make it stand out among the rest as much as possible. My wife and I got every upgrade available, and are already planning on immediately doing some custom flooring the day we get the keys (tiling the entire downstairs and all bathrooms). Home builders like Centex do offer a lot of choices, but they ONLY offer those choices; if you want something truly custom, you'll have to do it yourself once the home is yours.


5. DO include the entire family in the process as much as possible. We visit the home site a couple of times a week, at least, and take the kids so they can walk through it too. I tell ya, the kids do get real excited when they imagine how they will decorate their new room and of just living in the new house.

Buying a home and moving to a new location is a major event, tantamount to giving birth to a new baby (though hopefully you won't require Demerol to get through this process). So, celebrate it as a family before, during, and after! And, if you happen to be wanting to buy a new home in the San Antonio area, you should definitely look up my friends Terri Russo and Linda Wilkins. They will not steer you wrong.

Doug out.

Continue following our new home saga! "Closing Day" post here...

Posted by dougboude at 12:16 PM | PRINT THIS POST! | Link | 1 comment
11 June 2009
My Twelve Steps to a Coldbox App

Yesterday I had the privilege of providing my first consultation job as an instructor on the subject of Coldbox. The team that hired me are at the stage in their project where they're ready to start writing code (database is designed, UML and usecase diagrams are complete, mockups have been created), and they wanted to "experience" my thought processes, the questions I ask myself, my approaches to implementing functionality, and how I troubleshoot as I make my way from an idea to a working app in Coldbox. So, we spent the entire day together building an app from scratch, using Coldbox.

In preparation for the task, I spent the past week investing a LOT of time re-reading the Coldbox docs, experimenting, building out a small sample application that the team and I scoped out beforehand, and making notes about my thought/decision-making processes along the way.

Taking notes about your own personal development process is actually quite interesting and insightful, and since my audience found it useful and enlightening, I thought I'd share a high level view of it with the rest of the community as well. What follows is a bullet point list of how I personally generally go from idea to app.

Let's take a walk in my head, shall we? Don't be afraid....

1. let's get the current version of the coldbox framework (www.coldboxframework.com)


2. grab copy of the skeleton app template from the Coldbox framework download (coldbox\ApplicationTemplate)


3. make sure I have a mapping to Coldbox (mine is in application.cfc using this.mappings[...)


4. browse to the skeleton app and make sure that I get the pre-canned "You are now running Renew version 2.6.3..." home page.


5. Now, let's make a grocery list! What do I mean?....
The Coldbox framework (really more of a robust toolkit) does a LOT...which aspects, features, abilities do we want to incorporate into OUR application? Until you know what Coldbox has to offer, you can't answer this question. So, read through the online wiki my friend; open the ColdboxCheatSheet.pdf that comes in the framework's 'install' directory and take a good gander at all of the methods, plugins, interceptors, and other items listed there; Open up the Coldbox.xml.cfm file and just read the different settings that are listed there; Peruse the framework's directory structure, its config files, plugins, interceptors, autowiring, model management, views and layouts, usage of convention. As you learn about each new aspect, think about the app you are building and decide if it is one of the features you want to be sure and incorporate.


For this particular application, here's the grocery list I came up with when considering app features with framework features:

  • I will use the built in Coldbox model management as opposed to a third party IOC framework;
  • I will not use an  ORM framework for this app (though if the project warranted one, I most definitely would!);
  • I will be using Ajax so I'll want to take advantage of Coldbox's multiple layout ability;
  • I will be using my own security interceptor instead of the one that comes with Coldbox;
  • I will not use the environments interceptor;
  • I will be sure and enable the sidebar debugger;
  • I will make exclusive use of the MessageBox plugin for all system messaging

6. Okay, now I'll take a first pass through my config.xml.cfm file and alter the settings I know about at this point.

  • Enable model setter injection;
  • add custom settings for my javascript library path, my css path, my images path;
  • define the datasource object;
  • and enable the sidebar interceptor.

7. At this point, I feel the need to go ahead and create my database table structure and get that to a solid starting point.

8. Let's tweek the default layout and make placeholders for the different components it must organize (header, footer, nav, content, messages, dynamic content area, etc.).

9. Now i want to replace the pre-canned default view with one of my own...my app's own "you are here" landing page. On that page I'm now going to take the time to output lots of global data that I'll likely need to know how to get at later, like the datasource name, the name of the current event, etc. I will use this output as a cut-and-paste reference later.

10. Let's add some security with simulated authentication! Get a basic "login/logout" form to work without actually doing any database calls. The objective here is to just get the appropriate session variables in place, get them added to the Event object at the appropriate time, make sure our events are being intercepted and examined by security code at the appropriate places, and that rendered output is based on authentication status where it makes sense. Once it all works in simulation, add in the needed model objects to perform actual authentication and replace all simulation code.


11. Now I will focus on navigation (if it's anything but simple nav, such as database-driven, hierarchical nav) and ensure that all code is in place to create and output navigation appropriate for the user and state.


12. From here on out, I simply start going down the list of remaining functionality, typically ordered from "least specific" to "most specific", giving all end-user functionality priority over administrative functionality. The easy way to do this is to simply work my way through my navigation items, building out one at a time. To illustrate in more detail how I build out a specific piece of functionality (we'll say a CRUD operation), here's the check list:

  • build the handler with basic event functions to handle our nav links
  • build out the view page for managing an item
  • add a function for saving an item that saves then returns to the calling event
  • create a model service for the item...wire it up(using Coldbox's Model Integration feature
  • add the model service to the modelmapping.cfm
  • wire up the handler, finish up the handler functions that call the corresponding/appropriate service object's methods


In a nutshell, this is my general thought process as I build an app, with emphasis on building a Coldbox app. How does my "to do" list match up with everybody else's? I'd be interested to know!

Posted by dougboude at 10:58 AM | PRINT THIS POST! | Link | 5 comments