Get a free advice now!

    Pick the topic

    Developer OutsourcingWeb developingApp developingDigital MarketingeCommerce systemseEntertainment 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

    eCommerce growth – is your business ready?
    • Services
    • Trends

    eCommerce growth – is your business ready?

    April 8, 2024 by createIT
    Digital marketing without third-party cookies – new rules
    • Technology
    • Trends

    Digital marketing without third-party cookies – new rules

    February 21, 2024 by createIT
    eCommerce healthcheck
    • Services
    • Trends

    eCommerce healthcheck

    January 24, 2024 by createIT
    Live Visitor Count in WooCommerce with SSE
    • Dev Tips and Tricks

    Live Visitor Count in WooCommerce with SSE

    December 12, 2023 by createIT
    Calculate shipping costs programmatically in WooCommerce
    • Dev Tips and Tricks

    Calculate shipping costs programmatically in WooCommerce

    December 11, 2023 by createIT
    Designing a cookie consent modal certified by TCF IAB
    • Dev Tips and Tricks

    Designing a cookie consent modal certified by TCF IAB

    December 7, 2023 by createIT
    Understanding the IAB’s Global Vendor List (GVL)
    • Dev Tips and Tricks

    Understanding the IAB’s Global Vendor List (GVL)

    December 6, 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