WordPress upload and generate report from CSV file

Recently I was working on a project that required a CSV file uploader to upload CSV file into a WordPress directory and to show the CSV row data from the CSV file using a WordPress user meta that will vary from user to user and remain private. The user will not be able to see the user meta and the user meta will be given by the admin from the admin panel.

Today I am going to share with you how I have done the project.

Step 1:

First of all we have to create a CSV uploader plugin to upload the CSV file. We will create this plugins for only admin. For that we have to create a menu in the admin panel and have to take a form that will upload a file. The below code will do something like that. It will take only a CSV file as I have selected the file format specified to “CSV”. I have created a directory (csv_files_directory) in the theme folder where the CSV file will be uploaded.

The code will look something like this:

add_action('admin_menu', 'csv_upload_plugin_setup_menu');

function csv_upload_plugin_setup_menu(){

add_menu_page( 'CSV Uploader', 'CSV Uploader', 'manage_options', 'csv-upload-plugin', 'csv_init',get_template_directory_uri().'/images/csv.png' );


function csv_init(){



<div style="width:60%;margin:0 auto;position:relative;margin-top:15%;left:5%;">

<h1>Welcome to CSV file uploader</h1>

<h2>Upload a CSV File</h2>

<!-- Form to handle the upload - The enctype value here is very important -->

<form  method="post" enctype="multipart/form-data">

<input type='file' id='file_upload_csv' name='file_upload_csv'></input>

<?php submit_button('Upload') ?>




function csv_handle_post(){

// First check if the file appears on the _FILES array


$pdf = $_FILES['file_upload_csv'];

$allowed =  array('csv');

$filename = $_FILES['file_upload_csv']['name'];

$ext = pathinfo($filename, PATHINFO_EXTENSION);

if(!in_array($ext,$allowed) ) {

echo '<div id="message" class="updated"><p>Not a valid file format. <strong> Please Upload .csv file..</strong>.</p></div>';



// Use the wordpress function to upload

// file_upload_csv corresponds to the position in the $_FILES array

// 0 means the content is not associated with any other posts

$uploaded=media_handle_upload('file_upload_csv', 0);

// Error checking using WP functions


echo '<div id="message" class="updated"><p>Error uploading file: <strong>' . $uploaded->get_error_message().'</strong></p></div>';


echo '<div id="message" class="updated"><p>File upload successful!</p></div>';





function test_convert($id){

// Get the file details

$file = get_post($id);

// Get the data of the file as bytes


// plugin_dir_path(__FILE__) gets the location of the plugin directory

// Using preg replace to replace the directory sepeerators with the correct type

// This is where the output will be written to

$outputdir = preg_replace("[\/]", DIRECTORY_SEPARATOR, plugin_dir_path(__FILE__)) . "csv_files_directory".DIRECTORY_SEPARATOR;

//DIRECTORY_SEPARATOR ""(put your code here to create file title folder )";

echo '<div id="message"><p>'.$outputdir.'</p></div>';

if (!file_exists($outputdir)) {

mkdir($outputdir, 0777, true);



// This method is very improtant as it allows us access to the file system


// Write output

file_put_contents($outputdir.$file->post_title.".csv", $contents);

} catch (Exception $e){

echo '<div id="message" class="updated"><p>'.$e->getMessage() . '</p></div><br/>';





The output of the code will look something like this from the admin panel:

Step 2:

Now we have to create a user meta from where admin can assign a value to every user. From that value the user will be searched from the CSV file. I think creating a user meta is not a big deal for you. We just have to make the meta value private so that only admin can view or edit that. We will add a admin only function to the user meta and that will do the job.

function admin_only_function() {

global $current_user;

if($current_user->roles[0] == 'administrator') {

add_action( 'show_user_profile', 'extra_user_profile_fields' );

add_action( 'edit_user_profile', 'extra_user_profile_fields' );

function extra_user_profile_fields( $user ) { ?>

<h3 style="color:red;"><?php _e("Enter Your IFA Software Account Number", "blank"); ?></h3>

<table class="form-table">


<th><label for="account_number" style="color:green;"><?php _e("Enter IFA Account Number"); ?></label></th>


<input type="text" name="account_number" id="account_number" value="<?php echo esc_attr( get_the_author_meta( 'account_number', $user->ID ) ); ?>" /><br />

<span class="description"><?php _e("Please enter account number."); ?></span>



<?php }

add_action( 'personal_options_update', 'save_extra_user_profile_fields' );

add_action( 'edit_user_profile_update', 'save_extra_user_profile_fields' );

function save_extra_user_profile_fields( $user_id ) {

if ( !current_user_can( 'edit_user', $user_id ) ) { return false; }

update_user_meta( $user_id, 'account_number', $_POST['account_number'] );






The output will be similar to this:

Step 3:

Now the most important of all work is to create a page where the user will see the data that are assign to them by the admin by the user meta from the admin panel. We have to select a page where we will show the data of the user. We will make the page for logged in user. Other user will redirected to the home page.

First of all we will access the user meta field from the logged in user ID. Then we will search for the latest uploaded CSV file in that directory and will pick some columns for the CSV file (you can show all the rows if you wish).

After doing that we will search for those values where the searched user meta and the CSV columns matches and show the data to the user in table view.

The source code is something like this:


$current_user = wp_get_current_user();

$get_user_account_Number = get_usermeta( $current_user->ID, 'account_number' );

//to show the csv data by selected column

$picked  = array(5,18,22,7,3);

$theData = array();

//scan directory and search for latest modified folder

$theme_name = str_replace(array(' ', '<', '>', '&', '{', '}', '*'),array(''),strtolower(get_current_theme()));

$csv_file_directory = ABSPATH.'wp-content/themes/'.$theme_name.'/csv_files_directory/';

$files = scandir($csv_file_directory);


//get the lastest file uploaded in csv_files_directory/

$path = $csv_file_directory;

$latest_ctime = 0;

$latest_filename = '';

$directory = dir($path);

while (false !== ($entry = $directory->read())) {

$filepath = "{$path}/{$entry}";

//Check whether the entry is a file etc.:

if(is_file($filepath) && filectime($filepath) > $latest_ctime) {

$latest_ctime = filectime($filepath);

$latest_filename = $entry;

}//end if is file etc.

}//end while going over files in excel_uploads dir.
//$final_url = '/wp-content/themes/'.$theme_name.'/csv_files_directory/'.$latest_filename;

if (($handle = fopen("$csv_file_directory$latest_filename", "r")) !== FALSE) {

while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {

$numCols = count($data);

$row     = array();

for($c=0; $c < $numCols; $c++)

if(in_array($c, $picked))

$row[] = $data[$c];

$theData[] = $row;





//$result_array = sizeof($theData);
function searchForId($id, $array) {

$key_array = array();

foreach ($array as $key => $val) {

if ($val[2] === $id) {

$key_array[$key] = $key;



return $key_array;


$get_ids = array();

$get_ids = searchForId( $get_user_account_Number , $theData );


{   echo '<h3>Account Information</h3>';

echo '<table class="account-info-table">';

echo '<tr>

<th>IFA Software Account Number</th>

<th>Fund Name</th>

<th>Reg Total Units</th>

<th>Valuation Price</th>

<th>Valuation GBP</th>


foreach($get_ids as $get_id_key => $get_id_val){


echo '<tr>








echo '</table>';




//echo ' no data to show yet';



The result will look something like below:

Hope this article helped you a little. Thank you.

Saniul Ahsan

I picked PHP and JavaScript as a career start-up and developed a lot of applications using these. Like Management Application, Web Scrapping, Web API, E-Commerce Solutions, Finance Application etc. Outside of my professional life, I also do projects and code for reputation and my personal portfolio.