6

I am trying to convert a php/mysql generated table into a downloadable csv file. When a user enters search parameters, a call is made to a mysql table and results returned as table.

I used the solution offered in this thread and it works fabulously: Create a CSV File for a user in PHP

I am able to allow users to save or view the results as a csv file. the problem I am having is I'm not sure how to add column headers to the file. For example, the results that are returned are in the following format: $result[x]['office'], $result[x]['user'], etc..., but I also want to add column titles like "Office" and "User" so that anyone looking at the csv file immediately knows what the data means.

This is the function that generates the csv file:

    header("Content-type: text/csv");
    header("Content-Disposition: attachment; filename=$file.csv");
    header("Pragma: no-cache");
    header("Expires: 0");
    outputCSV($data);

function outputCSV($data) {
        $outstream = fopen("php://output", "a");
        function __outputCSV(&$vals, $key, $filehandler) {
            fputcsv($filehandler, $vals); // add parameters if you want
        }
        array_walk($data, "__outputCSV", $outstream);
        fclose($outstream);
    }

I have tried creating the following function, and then calling it right before I call outputCSV, but it is not successful:

function create_file_header()
{       
    $headers = 'Office, User, Tag, Value';
    $fp = fopen("php://output", "w");
    file_put_contents("$file.csv", $headers);
    fclose($fp);
}

Any help is greatly appreciated.

1

4 Answers 4

12

To create headers, you should just prepend a header row array and use fputcsv as normal.

You don't talk about the format of $data, but if it's an associative array you can do this for a generic solution:

function toCSV($data, $outstream) {
    if (count($data)) {
        // get header from keys
        fputcsv($outstream, array_keys($data[0]));
        // 
        foreach ($data as $row) {
            fputcsv($outstream, $row);
        }
    }
}

I'm don't see the benefit of array_walk() over a foreach loop.

Sign up to request clarification or add additional context in comments.

Comments

2

Do this before calling outputCSV:

array_unshift($data, array('Office', 'User', 'Tag', 'Value'));

Or, if the elements of $data are associative arrays, this would be more dynamic:

array_unshift($data, array_keys($data[0]));

1 Comment

This is a genius solution! I ended up using array_push() in a slightly different case, but this is perfect for someone getting the header columns in MySQL by using fetch_fields() and then appending more fields to them. Kudos.
0

Couldn't you just put it in the outputCSV function?

header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=$file.csv");
header("Pragma: no-cache");
header("Expires: 0");
outputCSV($data);

function outputCSV($data) {
    $outstream = fopen("php://output", "a");

    $headers = 'Office, User, Tag, Value';
    fwrite($outstream,$headers);

    function __outputCSV(&$vals, $key, $filehandler) {
        fputcsv($filehandler, $vals); // add parameters if you want
    }
    array_walk($data, "__outputCSV", $outstream);
    fclose($outstream);
 }

1 Comment

Just a note. In my experience, I needed to add ."\r\n" at the end of $headers = 'Office, User, Tag, Value' line, i.e. $headers = 'Office, User, Tag, Value'."\r\n" or the first row would be appended to the header row without line break.
0

Add an optional $headers parameter to your outputCSV function. If your code passes them, they will be prepended to the csv array:

outputCSV($data, array('Office', 'User'));

//

function outputCSV($data, $headers = null) {
    $outstream = fopen("php://output", "a");
    function __outputCSV(&$vals, $key, $filehandler) {
        fputcsv($filehandler, $vals); // add parameters if you want
    }
    if ($headers) {
        $data = array_merge(array($headers), $data);
    }
    array_walk($data, "__outputCSV", $outstream);
    fclose($outstream);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.