Importing Data From a CSV File Into a Wordpress ACF Repeater Field

Technical and very niche content inbound!

**18th April 2022 — This has been edited to fix an issue where updating post meta would quite often break the import, so now instead of updating as an array we use multiple update_post_meta function calls.**

Photo by Mika Baumeister on Unsplash

Recently I hit upon a problem which other Wordpress developers who use ACF have come across before I’m sure. A quick Google tells me some people may have come across this issue before, but surely more people have hit this, right?

If you’re looking for the full solution without reading any of the workings out then scroll right to the bottom of the page.

The Problem

You’ve created a shiny new post type, and within that post type you’ve got an ACF repeater to display some data in a consistent format. You then get an email from the client with 200 pieces of information in a spreadsheet they want to drop in. Who’s going to do all of that data entry? I bet you didn’t budget for it!

This happened to me most recently from a client who runs events, and within each event they have a list of competitors. The event in question was a four day long tournament with 200 competitors and they needed to list out the start date for each one.

The Solution

To get around this I wrote a super simple plugin which is highly customised for my needs — your own needs will be different, but here’s a run through of how it was built and the full code reference is at the bottom of the page for you to copy for your own gains.

Step 1: Create a Meta Box

A snippet of code which shows adding a metabox — full copyable code at the end of the article

This snippet will create the meta box in the sidebar — more documentation around adding meta boxes can be found here, the most important things to note are parameters 2 (the title on the page), 3 (the callback function) and 4 (what post type it will appear on)

Step 1.1: Update your Post Form

A snippet of code which shows changing the form submit type — full copyable code at the end of the article

This is a gotcha which confused me for a while — the default form for Wordpress events isn’t configured to allow files to be uploaded, so this will simply update that to allow the csv file to be uploaded when you save the post.

Step 2: Add the Input to your Metabox

A snippet of code which shows adding an input to a metabox — full copyable code at the end of the article

Remember that callback function we defined in parameter 3 of the meta box function — well that’s this function. This very simply outputs an input and a label to allow people to upload their csv file.

Step 3: Some Security

A snippet of code which shows adding security checks to a wordpress function — full copyable code at the end of the article

This just does some basic checking to make sure whoever is uploading the file can actually do that and there’s a NONCE set. Note at the bottom of the file where there’s a check for 'events' == $_POST['post_type'] you’ll need to change this for your own post type.

Step 4: Do the magic

So this is where the magic is actually happening. What we’re doing is (simply put)…

  1. Taking the file and putting it into the uploads directory using the wp_upload_bits() function.
  2. Opening the file with fopen() , turning it into an array and then looping through all of the lines in the file.
  3. For each line we’re updating post meta to power the ACF repeater and incrementing a counter
  4. Once the loop has ended and we’ve closed the file out. We call update_post_meta() with the count of how many rows we’ve inserted and the computed name of the field (more on that in a second) to make the backend display work properly.

Simple right? Thank you and goodbye.

Hang on a second… I’m confused… what’s going on here?

Fair question. You probably need to see the ACF Field group to really get an idea of what’s going on

A screenshot of the ACF Field Group which is being talked about in the article.

So here we have the field group, note how the field name is first_match_details — well that matches with the first section of our array entry

first_match_details_’ . $i . ‘_category’ => $line[0],`

Then the first field we’re looking at is Category, or the field name category , which makes up the second part of our array entry

‘first_match_details_’ . $i . ‘_category’ => $line[0],

You probably noticed that under each of the useful pieces of information we were pumping into the database there was a static piece of text that used the same array key, but with an _ at the start, well that text is the Key associated with each field and is required to help ACF know what’s going on.

'_first_match_details_'. $i . '_category' => 'field_6151d21c5f392',
A screenshot of the single field which is being discussed above that shows the field key is the same as the data which is being pumped into the database

Ok that’s great, but what about your file?

So a bit more background information on the file I’m uploading, it looks a bit like this:

B112, Smith, John, Friday 12:00
B112, Temple, Shirley, Friday 12:15
B112, Parton, Dolly, Friday 12:20

Which accounts for this section of the array we’re dropping in.

’first_match_details_’ . $i . ‘_category’ => $line[0],`

And why did you do that last step, the one which just updated with a number?

update_post_meta($post_id, 'first_match_details', $i);
update_post_meta($post_id, '_first_match_details', 'field_6151d1f75f391');

This bit? It tells ACF how many rows of data we have in total for that repeater. The first line is just the field name, and the second part with the _ at the start is updated with the field name from the admin section.

Wrap Up

Here’s the full Gist of things, feel free to use as you see fit and hopefully it will help you if you ever run into the same issue of trying to update hundreds of rows of repeaters!

If you’ve tried this out and it’s not worked for you / you have any questions about this or general Wordpress development then feel free to @ me on Twitter



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store