Get a free advice now!

    Pick the topic

    [checkbox* "Developer Outsourcing" "Web developing" "App developing" "Digital Marketing" "eCommerce systems" "eEntertainment systems"]

    Thank you for your message. It has been sent.

    Tags

    FOOEvents – generate a custom CSV report

    FOOEvents – generate a custom CSV report

    Challenge: prepare a list of all attendees in the CSV format
    Solution: fetch data from the database using a custom PHP method


    If you sell tickets or provide booking services, your choice was probably FooEvents, which is the most popular WordPress plugin in this category. Exporting a list of all attendees to the CSV format can be a handy feature. In this article, we will learn how to do this!

    Event Export

    The built-in function allows exporting event details (attendees), including unpaid tickets and billing details. Just go to Edit Product (WooCommerce), click the ‘Event Export’ tab, and the button ‘Download CSV of attendees’ will be available to use.

    WordPress dashboard with the event export category opened

    The function is doing its job: exporting single product (single event) attendees to a preformatted Excel CSV file. However, what about a situation when we would like to have a formatted file with all the data (all events and all attendees)? We will implement a custom function that will query the database, collect data and create a CSV to download.

    Simple WP plugin

    Our simple WordPress plugin will have 1 php file. By adding a special PHP comment, we will force WordPress to recognize it as a plugin and we will be able to activate it in the Wp-admin / Plugins section.

    <?php
    // wp-content/plugins/ct-custom-csv-report/ct-custom-csv-report.php
    /**
     * Plugin Name: Foo CSV Export
     * Description: Custom CSV Report for FooEvents
     * Version: 1.0
     * Author: createIT
     */
    
    WordPress dashboard with the Plugins section opened

    FooEvents custom list

    The first function will be executed on admin_init hook. The list of all WooCommerce orders with additional details and the list of attendees will be displayed. We will also have additional input “Show orders from”, which will filter order list by date. We will use the WC order object to get details of the orders.

    White page with dark text and a few buttons
    /**
     * FooEvents - display all orders and Attendees details
     */
    add_action("admin_init", "ct_display_report5");
    function ct_display_report5()
    {
        if (!current_user_can('administrator')) {
            return false;
        }
        if (!isset($_GET['ct_display_report5'])) {
            return false;
        }
        ct_get_events_data();
    }
    function ct_get_events_data($flat_data = false)
    {
        $html = '';
        $html .= '
     <style> 
     table {
         caption-side: bottom;
         border-collapse: collapse;
         width: 100%;
         margin-bottom: 1rem;
         color: #212529;
         vertical-align: top;
         border-color: #dee2e6;
    }
     td {
         vertical-align:top;
    }
     .container {
         max-width:1280px;
         margin:0 auto;
    }
     body {
         background:#ccc;
    }
     .item {
         background:#fff;
         padding:20px;
         margin:20px 0;
         border-radius:20px;
    }
     .button {
         padding:10px 20px;
         background:#ccc;
         border:0;
         color:#000;
         text-decoration: none;
         margin: 10px;
         display: inline-block;
         cursor:pointer;
    }
     .moreText {
         display:inline-block;
         margin:15px 0;
    }
     .title {
         margin:30px 0 0 0;
    }
     .itemNumber {
         font-size: 18px;
         background: #000;
         color: #fff;
         padding: 7px;
         margin: 0 5px 5px 0;
         display: inline-block;
    }
        </style>
        ';
    
        $orders_from_date = isset($_GET['orders_from']) ? $_GET['orders_from'] : '';
        $html .= '<div class="container">';
        $html .= '<div class="item">';
        $download_csv_url = '/wp-admin/?ct_custom_download_123=yes';
        if ($orders_from_date) {
            $download_csv_url = '/wp-admin/?ct_custom_download_123=yes&orders_from=' . $orders_from_date;
            $title = 'Orders from: ' . $orders_from_date;
            $download_csv_text = '? Export orders';
            $more_text = 'To generate CSV file with orders from ' . $orders_from_date . ' click here:';
        } else {
            $title = 'Orders all-time';
            $download_csv_text = '? Export orders';
            $more_text = 'To generate CSV file with ALL orders click here:';
        }
        $html .= '<h2>' . $title . '</h2>';
        $html .= '<p><span class="moreText">' . $more_text . '</span><br><a href="' . $download_csv_url . '" style="display:inline-block; text-decoration:none; text-transform:uppercase; font-size:18px; background:#000; color:#fff; padding:8px 16px;">' . $download_csv_text . '</a></p>';
        $html .= '<p><hr></p>';
        $html .= '<h4 class="title">Filters</h4>';
        $html .= '<form action="/wp-admin/">';
        $html .= '<label>Show orders from: <input type="date" name="orders_from" value="' . $orders_from_date . '"></label>';
        $html .= '<input type="hidden" name="ct_display_report5" value="yes" />';
        $html .= '<input type="submit" value="Go" class="button">';
        $html .= '<a href="/wp-admin/?ct_display_report5=yes" class="button">Reset filters</a>';
        $html .= '</form>';
        $html .= '</div>';
        // compose data
        $csv_data = array();
        $columnsNames = array();
        $args = array(
            'limit' => -1,
            'orderby' => 'date',
            'order' => 'DESC',
        );
        if ($orders_from_date) {
            $args['date_created'] = '>' . (strtotime($orders_from_date));
        }
        $query = new WC_Order_Query($args);
        $orders = $query->get_orders();
        $counter = 0;
        $attendeeCounter = 0;
        foreach ($orders as $order) {
            $counter++;
            $html .= '<div class="item">';
            $html .= '<table><tr>';
            $html .= '<td><span class="itemNumber">' . $counter . '.</span></td>';
            $html .= '<td>';
            $html .= '<p>';
            $order_items = $order->get_items();
            $html .= '<p><strong>Order details:</strong>' . '<br>';
            $data1 = '';
            $html .= 'Order number: <a href="' . $order->get_edit_order_url() . '" target="_blank">' . $order->get_order_number() . '</a><br>';
            $data1 .= $order->get_date_created() . '<br>';
            foreach ($order_items as $item_id => $item) {
                $product_name = $item['name'];
                $item_quantity = $order->get_item_meta($item_id, '_qty', true);
                $data1 .= $item_quantity . ' x ' . $product_name . '<br>';
            }
            $data1 .= $order->get_total() . '<br>';
            $html .= $data1;
            $html .= '</p>';
            $data2 = '';
            $html .= '<p><strong>Billing:</strong>' . '<br>';
            $data2 .= $order->get_formatted_billing_address();
            $data2 .= $order->get_billing_email() . '<br>';
            $data2 .= $order->get_billing_phone() . '<br>';
            $html .= $data2;
            $html .= '</p>';
            $html .= '</td>';
            $html .= '<td>';
            $html .= '<p><strong>Additional Fields:</strong>' . '<br>';
            $data3 = '';
            $data3 .= 'Title: ' . $order->get_meta('additional_contact_title') . '<br>';
            $data3 .= 'First Name: ' . $order->get_meta('additional_contact_first_name') . '<br>';
            $data3 .= 'Last Name: ' . $order->get_meta('additional_contact_last_name') . '<br>';
            $data3 .= 'Registration E-mail: ' . $order->get_meta('additional_contact_email') . '<br>';
            $data3 .= 'E-mail who will receive on-site alerts: ' . $order->get_meta('additional_contact_alert') . '<br>';
            $data3 .= 'Job Title: ' . $order->get_meta('additional_contact_position') . '<br>';
            $data3 .= 'Phone: ' . $order->get_meta('additional_contact_phone') . '<br>';
            $html .= $data3;
            $html .= '</p>';
            $html .= '</td>';
            $html .= '<td>';
            $details = $order->get_meta('WooCommerceEventsOrderTickets');
            $html .= '<p><strong>Attendees:</strong></p>';
            $data4 = '';
            foreach ($details as $customAttendee) {
                foreach ($customAttendee as $key1 => $ticket) {
                    $attendeeCounter++;
                    $data4 .= '<strong>' . get_the_title($ticket['WooCommerceEventsProductID']) . '</strong><br>';
                    $data4 .= '<strong>Attendee ' . ($key1) . '</strong>' . '<br>';
                    $data4 .= 'WooCommerceEventsPurchaserFirstName: ' . $ticket['WooCommerceEventsPurchaserFirstName'] . '<br>';
                    $data4 .= 'WooCommerceEventsPurchaserLastName: ' . $ticket['WooCommerceEventsPurchaserLastName'] . '<br>';
                    $data4 .= 'WooCommerceEventsPurchaserEmail: ' . $ticket['WoCommerceEventsPurchaserEmail'] . '<br>';
                    // collect attendee data for CSV lines
                    $columnsNames['WooCommerceEventsProductID'] = '---';
                    $columnsNames['AttendeeCounter'] = '---';
                    $csv_data[$attendeeCounter]['WooCommerceEventsProductID'] .= get_the_title($ticket['WooCommerceEventsProductID']);
                    $csv_data[$attendeeCounter]['AttendeeCounter'] .= 'Attendee ' . ($key1);
                    $csv_data[$attendeeCounter]['WooCommerceEventsPurchaserFirstName'] = $ticket['WooCommerceEventsPurchaserFirstName'];
                    $csv_data[$attendeeCounter]['WooCommerceEventsPurchaserLastName'] = $ticket['WooCommerceEventsPurchaserLastName'];
                    $csv_data[$attendeeCounter]['WooCommerceEventsPurchaserEmail'] = $ticket['WoCommerceEventsPurchaserEmail'];
                    $columnsNames['WooCommerceEventsPurchaserFirstName'] = '---';
                    $columnsNames['WooCommerceEventsPurchaserLastName'] = '---';
                    $columnsNames['WooCommerceEventsPurchaserEmail'] = '---';
                    foreach ($ticket['WooCommerceEventsCustomAttendeeFields'] as $key => $val) {
                        $data4 .= $key . ': ' . $val . '<br>';
                        $csv_data[$attendeeCounter][$key] = $val;
                        $columnsNames[$key] = '---';
                    }
                    $data4 .= '<br>';
                }
            }
            $html .= $data4;
            $html .= '</td>';
            $html .= '</tr></table>';
            $html .= '</div>';
        }
        $html .= '</div> <!-- // container -->';
        $html .= '<hr>';
        if ($flat_data) {
            return array($csv_data, $columnsNames);
        }
        echo $html;
        die("end");
    }
    

    We can filter orders using the creation date. The Datepicker (native) will be displayed and will allow to restrict dates of the exported list.

    Black & white page with a calendar

    ct_get_events_data() also has an additional purpose. It gathers data for the CSV generation functionality. When executed with an additional parameter, it will return data (instead of displaying it). Here is the ct_generate_csv_from_array() function that will compose a CSV file and trigger the download.

    /**
     * FooEvents - generate custom CSV
     */
    function ct_custom_download_123()
    {
        if (isset($_GET["ct_custom_download_123"])):
            if (!current_user_can('administrator')) {
                return false;
            }
            $data = ct_get_events_data(true);
            ct_generate_csv_from_array($data[0], $data[1]);
        endif;
    }
    add_action("init", "ct_custom_download_123");
    function ct_generate_csv_from_array($data, $columns)
    {
        if (current_user_can('administrator')):
            if (is_admin()):
                // add columns
                $columns_names = array_keys($columns);
                $filename_variation = 'all-';
                $orders_from_date = isset($_GET['orders_from']) ? $_GET['orders_from'] : '';
                if ($orders_from_date) {
                    $filename_variation = 'from' . $orders_from_date;
                }
                foreach ($data as $key => $line) {
                    // var_dump($line);
                    $data[$key] = array_merge($columns, $line);
                }
                $csv_filename = "report-" . $filename_variation . time() . ".csv";
                header('Content-Type: text/csv');
                header('Content-Disposition: attachment; filename="' . $csv_filename . '"');
                $fp = fopen('php://output', 'wb');
                $myCounter = 0;
                // add column names as 0 rows
                array_unshift($data, $columns_names);
                foreach ($data as $key => $line) {
                    $line = json_decode(json_encode($line), true);;
                    // clean up html
                    $breaks = array("<br />", "<br>", "<br/>");
                    $line = str_ireplace($breaks, "\r\n", $line);
                    $remove = array("<strong>", "</strong>");
                    $line = str_ireplace($remove, "", $line);
                    fputcsv($fp, $line, ',');
                    $myCounter = $myCounter + 1;
                }
                fclose($fp);
                exit;
            endif;
        endif;
    }
    Animation of a black & white page with buttons

    Dashboard metabox

    It would be nice to have a custom dashboard metabox with a special button. On click, we will be redirected to the custom fooEvents list of orders. Here is the code:

    /**
     * FooEvents - display dashboard metabox with button
     */
    add_action('wp_dashboard_setup', 'my_custom_dashboard_widgets');
    function my_custom_dashboard_widgets()
    {
        wp_add_dashboard_widget('ct_custom_help_widget', 'Export Custom report to CSV', 'ct_custom_dashboard_help');
    }
    function ct_custom_dashboard_help()
    {
        echo '<a href="/wp-admin/?ct_display_report5=yes" class="button button-primary">Show all orders and events</a>';
    }
    
    WordPress dashboard with Export Custom report to CSV option opened

    CSV format

    The generated CSV file will have a random name (including the current timestamp), each attendee data will be placed in a separate row, each column being a custom field. The script will display all custom fields attached to a particular order. In our Excel CSV file, we have 25 columns (including all custom order fields).

    Excel table with data

    Source code

    Our plugin source code for displaying a custom order list and exporting data to a CSV file is available to download at GitHub. Feel free to clone it and test it out! Repository: https://github.com/createit-dev/151-fooevents-generate-custom-report-export-to-csv

    That’s it for today’s tutorial. Subscribe to our newsletter and stay up-to-date on other useful articles.

    Comments
    0 response

    Add comment

    Your email address will not be published. Required fields are marked *

    Popular news

    PHPStorm – fix long load time of a directory window
    • Dev Tips and Tricks

    PHPStorm – fix long load time of a directory window

    January 20, 2023 by createIT
    reCAPTCHA v3 – WordPress implementation
    • Dev Tips and Tricks

    reCAPTCHA v3 – WordPress implementation

    January 20, 2023 by createIT
    How to compare GIT and server files
    • Dev Tips and Tricks

    How to compare GIT and server files

    January 19, 2023 by createIT
    How to trigger a click event inside iframe?
    • Dev Tips and Tricks

    How to trigger a click event inside iframe?

    January 19, 2023 by createIT
    FOOEvents – generate a custom CSV report
    • Dev Tips and Tricks

    FOOEvents – generate a custom CSV report

    January 19, 2023 by createIT
    Headless chrome – testing webgl using playwright
    • Dev Tips and Tricks

    Headless chrome – testing webgl using playwright

    January 18, 2023 by createIT
    Preview big SQL files with PilotEdit
    • Dev Tips and Tricks

    Preview big SQL files with PilotEdit

    January 18, 2023 by createIT
    Outsourcing a team of backend developers
    • Our Highlights

    Outsourcing a team of backend developers

    January 18, 2023 by createIT
    A new look for an aspiring brand
    • Our Highlights

    A new look for an aspiring brand

    January 18, 2023 by createIT
    Percy AI visual regressions – playwright example
    • Dev Tips and Tricks

    Percy AI visual regressions – playwright example

    January 17, 2023 by createIT

    Support – Tips and Tricks
    All tips in one place, and the database keeps growing. Stay up to date and optimize your work!

    Contact us