How To Export Posts To CSV In WordPress

Add Custom Button On The Post Listing

To generate the CSV, we first need to give a button on the listing page of a post screen. On the click of this button, we will write a code for generating a CSV.

Open your functions.php file and place the below code in it.

1
2
3
4
5
6
7
8
9
10
add_action( 'manage_posts_extra_tablenav', 'admin_post_list_top_export_button', 20, 1 );
function admin_post_list_top_export_button( $which ) {
    global $typenow;
    if ( 'post' === $typenow && 'top' === $which ) {
        ?>
        <input type="submit" name="export_all_posts" id="export_all_posts" class="button button-primary" value="Export All Posts" />
        <?php
    }
}

Above code add the button ‘Export All Posts’ on the posts listing as shown in the screenshot. Here, we have used the hook manage_posts_extra_tablenav to place our custom button on post screen page.

Export Post Button

Actual Code Which Export Posts To CSV

At this stage, you are ready with your custom button which should generate our CSV. So, let’s add a code that generates the CSV on the click of a button and send it to the browser for download.

Add the below code in the functions.php file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
add_action( 'init', 'func_export_all_posts' );
function func_export_all_posts() {
    if(isset($_GET['export_all_posts'])) {
        $arg = array(
                'post_type' => 'post',
                'post_status' => 'publish',
                'posts_per_page' => -1,
            );
        global $post;
        $arr_post = get_posts($arg);
        if ($arr_post) {
            header('Content-type: text/csv');
            header('Content-Disposition: attachment; filename="wp.csv"');
            header('Pragma: no-cache');
            header('Expires: 0');
            $file = fopen('<a style="box-sizing: content-box !important; border: 0px !important; font-family: Monaco, consolas, 'bitstream vera sans mono', 'courier new', Courier, monospace !important; font-size: 1em !important; font-style: normal !important; font-weight: 400 !important; margin: 0px !important; outline: 0px !important; padding: 0px !important; vertical-align: baseline !important; background: 0px 0px !important; color: blue !important; text-decoration: none; transition: all 0.2s linear 0s; border-radius: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 1.1em !important; overflow: visible !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; width: auto !important; direction: ltr !important; box-shadow: none !important;" href="php://output/">php://output</a>', 'w');
            fputcsv($file, array('Post Title', 'URL'));
            foreach ($arr_post as $post) {
                setup_postdata($post);
                fputcsv($file, array(get_the_title(), get_the_permalink()));
            }
            exit();
        }
    }
}

The Absurdly Underestimated Dangers of CSV Injection

Hey, just for fun let’s try something, let’s modify our CSV file to the following

UserId,BillToDate,ProjectName,Description,DurationMinutes
<span class="hljs-number">1</span>,<span class="hljs-number">2017</span>-<span class="hljs-number">07</span>-<span class="hljs-number">25</span>,Test Project,Flipped the jibbet,<span class="hljs-number">60</span>
<span class="hljs-number">2</span>,<span class="hljs-number">2017</span>-<span class="hljs-number">07</span>-<span class="hljs-number">25</span>,Important Client,<span class="hljs-string">"Bop, dop, and giglip"</span>, <span class="hljs-number">240</span>
<span class="hljs-number">2</span>,<span class="hljs-number">2017</span>-<span class="hljs-number">07</span>-<span class="hljs-number">25</span>,Important Client,<span class="hljs-string">"=2+5"</span>, <span class="hljs-number">240</span>