Notes

Note: If PHP is not properly recognizing
the line endings when reading files either on or created by a Macintosh
computer, enabling the
auto_detect_line_endings
run-time configuration option may help resolve the problem.

I found that the fputcsv examples for PHP 4 missed one thing, that was proper handling of the $enclosure value when it is a quote (if a quote is passed in a field, and it is delimited by a slash, it will be improperly handled by the functions submitted here).

My modified function was built using the actual PHP5 source for fputcsv, with the addition of properly reacting to the existence of a delimited quote in the field being processed.

Alright, after playing a while, I'm confident the following replacement function works in all cases, including the ones for which the native fputcsv function fails. If fputcsv fails to work for you (particularly with mysql csv imports), try this function as a drop-in replacement instead.

Arguments to pass in are exactly the same as for fputcsv, though I have added an additional $mysql_null boolean which allows one to turn php null's into mysql-insertable nulls (by default, this add-on is disabled, thus working identically to fputcsv [except this one works!]).

Using fputcsv to output a CSV with a tab delimiter is a little tricky since the delimiter field only takes one character.The answer is to use the chr() function. The ascii code for tab is 9, so chr(9) returns a tab character.

it should be:<?php fputcsv($fp, $foo, "\t");?>you just forgot that single quotes are literal...meaning whatever you put there that's what will come out so '\t' would be same as 't' because \ in that case would be only used for escaping but if you use double quotes then that would work.

I've created a function for quickly generating CSV files that work with Microsoft applications. In the field I learned a few things about generating CSVs that are not always obvious. First, since PHP is generally *nix-based, it makes sense that the line endings are always \n instead of \r\n. However, certain Microsoft programs (I'm looking at you, Access 97), will fail to recognize the CSV properly unless each line ends with \r\n. So this function changes the line endings accordingly. Secondly, if the first column heading / value of the CSV file begins with uppercase ID, certain Microsoft programs (ahem, Excel 2007) will interpret the file as being in the SYLK format rather than CSV, as described here: http://support.microsoft.com/kb/323626

This function accommodates for that as well, by forcibly enclosing that first value in quotes (when this doesn't occur automatically). It would be fairly simple to modify this function to use another delimiter if need be and I leave that as an exercise to the reader. So quite simply, this function is used for outputting CSV data to a CSV file in a way that is safe for use with Windows applications. It takes two parameters + one optional parameter: the location of where the file should be saved, an array of data rows, and an optional array of column headings. (Technically you could omit the headings array and just include it as the first row of the data, but it is often useful to keep this data stored in different arrays in practice.)

Unexpected (to me) behaviour: the enclosure characters inside the strings are doubled *unless* they're preceded by a backslash. If the enclosure is preceded by a backslash it's considered to be already escaped.

Inspired by boonerunner's function, I wrote a smaller, faster, and more flexible one, which also uses less memory.I also renamed it to avoid collision or overwriting the PHP function, and gave the 3rd and 4th parameter default values like fputcsv() uses.

This function puts all text values in $enclosure's while doubling the $enclosure in the value, and leaves numeric values as they are.But if the $delimiter exists in the numeric value, this value will also be put in $enclosure's (may happen if you use a dot as the $delimiter).

Here is an adaption of the above code that adds support for double quotes inside a field. (One double quote is replaced with a pair of double quotes per the CSV format).

<?phpfunction fputcsv($filePointer,$dataArray,$delimiter,$enclosure) {// Write a line to a file // $filePointer = the file resource to write to // $dataArray = the data to write out // $delimeter = the field separator

// Build the string$string = "";

// No leading delimiter$writeDelimiter = FALSE; foreach($dataArray as $dataElement) {// Replaces a double quote with two double quotes$dataElement=str_replace("\"", "\"\"", $dataElement);

// Adds a delimiter before each field (except the first)if($writeDelimiter) $string .= $delimiter;

// Encloses each field with $enclosure and adds it to the string$string .= $enclosure . $dataElement . $enclosure;

// Delimiters are used every time except the first.$writeDelimiter = TRUE; } // end foreach($dataArray as $dataElement)

[EDIT BY danbrown AT php DOT net: This is a revised function with a few bugfixes and improvements done by this author. The original function example was written by arthur AT mclean DOT ws, and rewritten between by arthur AT korn DOT ch.]

- when calling str_replace(), you must assign $cell the return value or nothing gets saved

- when using strchr(), you should explicitly check !== FALSE, or it'll treat a return value of 0 (found the character at string position 0) as FALSE

- Excel seems to quote not only fields containing commas, but fields containing quotes as well, so I've added another strchr() for quotes; I'm not saying Microsoft knows the correct way for sure, but it seems reasonable to me

- the original function put a space after each comma; that might be legal, I don't know, but I've never seen it (and I don't think it is, because then how would you indicate you wanted a field to start with a space other than by quoting it?)

- the original function didn't correctly return the length of the data outputted

In general I found myself wanting to get the result as a string rather than writing it to a file, and in particular I wanted to produce a CSV using an EOL that might not be the same as that on the server where I generated it. This is how I solved the problem without rewriting fputcsv.

So this is something I wrote to generically generate CSV exports from 2 arrays and a name.

You need to provide it with e single dimension array for the headings. A multidimensional array with the actual body . And lastly the filename you would like to get minus the .csv and viola.

<?php

# We will use this function to generate a CSVfunction exportCSV($headings=false, $rows=false, $filename=false) {# Ensure that we have data to be able to export the CSVif ((!empty($headings)) AND (!empty($rows))) {# modify the name somewhat$name = ($filename !== false) ? $filename . ".csv" : "export.csv";

# Set the headers we need for this to workheader('Content-Type: text/csv; charset=utf-8');header('Content-Disposition: attachment; filename=' . $name);

# Start the ouput$output = fopen('php://output', 'w');

# Create the headersfputcsv($output, $headings);

# Then loop through the rowsforeach($rows as $row) {# Add the rows to the bodyfputcsv($output, $row); }