Create Downloadable CSV File with Ajax Call in WordPress wp-admin page

Recently I was tasked to create add a button to a page in wp-admin which when clicked will create a downloadable csv file and start downloading it. The page in wp-admin was created with Advanced Custom Fields Pro (ACF). Since ACF doesn’t have field for simple button input type so I created one with ACF add-on called “Advanced Custom Fields: Extended”. The goal was to add click event listener to the button input in jQuery, downloadable csv file and start downloading it or show Save As dialog depending upon the browser.

Download CSV Report Button

Step one was to add a javascript file in the wp-admin to handle the code logic for the “Download Report” button. I added the following code to the functions.php file of theme:

add_action('acf/input/admin_enqueue_scripts', 'ethos_acf_admin_enqueue_scripts');
function ethos_acf_admin_enqueue_scripts() {
    wp_enqueue_script( 'ethos-acf-input-js', get_stylesheet_directory_uri() . '/admin/script.js', false, '1.0.0' );

    wp_localize_script( 'mysite-input-js', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
}

The above piece of code includes /admin/script.js file from the theme folder and also pass ajax_object variable object to the script.js file.

Step two was to add event listener in functions.php file for ajax calls. I added the following piece of code for listening to ajax call associated with the “Download Report” button.

add_action('wp_ajax_download_zipcodes_report', 'download_zipcodes_report_handler');
add_action('wp_ajax_nopriv_download_zipcodes_report', 'download_zipcodes_report_handler');

function download_zipcodes_report_handler() {
    return generate_zipcodes_report(get_field('delivery_zipcode_search_stats', 'option'));
}

As you can see that the Ajax call handler function download_zipcodes_report_handler calls generate_zipcodes_report function to create a csv file. Following is the generate_zipcodes_report function which creates a csv report file and sends it back to the Ajax call made from Javascript in response to the “Download Report” button click:

function generate_zipcodes_report($array, $filename = "export.csv", $delimiter=";") {
    // tell the browser it's going to be a csv file
    header('Content-Type: text/csv; charset=utf-8');
    
    // tell the browser we want to save it instead of displaying it
    header('Content-Disposition: attachment; filename=export.csv');

    // open the "output" stream
    // see http://www.php.net/manual/en/wrappers.php.php#refsect2-wrappers.php-unknown-unknown-unknown-descriptioq
    $f = fopen('php://output', 'w');

    // use keys as column titles
    fputcsv( $f, array_keys( $array['0'] ) , $delimiter );

    foreach ($array as $line) {
        fputcsv($f, $line, $delimiter);
    }
}

 

The last step was to add jQuery code to the admin/script.js file to handle the “Download Report” button click in the wp-admin page. Following is the jQuery  script which I used to make Ajax call upon “Download Report” button click:

jQuery(document).on( 'click', '#zipcodes_export_btn', function(e) {
    e.stopPropagation();

    jQuery.ajax({
        type:"POST",
        url:ajax_object.ajax_url,
        data: {action:'download_zipcodes_report'},
        success:function(res){
            //console.log(res);

            /*
               * Make CSV downloadable
               */
            var downloadLink = document.createElement("a");
            var fileData = ['\ufeff'+res];

            var blobObject = new Blob(fileData,{
               type: "text/csv;charset=utf-8;"
             });

            var url = URL.createObjectURL(blobObject);
            downloadLink.href = url;
            downloadLink.download = "zipcodes_report.csv";

            /*
             * Actually download CSV
             */
            document.body.appendChild(downloadLink);
            downloadLink.click();
            document.body.removeChild(downloadLink);
        }
    });
});

This piece of jQuery code does the following:

  1. Creates a csv file in the browser using modern Javascript standards
  2. Adds temporary link tag to the page
  3. Triggers the click on the temporary link tag
  4. Show “Save As” dialog in FireFox or start downloading the csv in Chrome/Safari

I hope this piece of code will help some of you as myself looked for the solution but didn’t find one specifically for my case.