Bulk scheduling from a spreadsheet: how to build a clean upload file
A month of posts in one upload only works if the sheet is clean. How to structure columns, dates, media and alt text so every row passes on the first try.

Bulk scheduling sounds like a shortcut: fill a spreadsheet, upload it, and a month of posts appears on the calendar. In practice the upload is the easy part. What decides whether it takes five minutes or an afternoon is the sheet itself. A file with mixed date formats, captions pasted with stray line breaks and image links that only work when you are signed in will fail row by row. This guide covers how to build an upload file that passes the first time, whichever scheduler you use, and what to check before you press upload.
Why bulk upload goes wrong
Most failed uploads come from a handful of causes, and almost none of them are about the scheduler:
- Dates that mean two things. 03/11/2026 is 3 November in most of the world and March 11 in the United States. A spreadsheet app may also have quietly turned a typed date into a number or a different format.
- Times without a time zone. “10:00” means nothing until you know whose 10:00. If the client is in Toronto and you are in Lisbon, someone has to decide.
- Media that the network cannot fetch. A link to a shared drive folder, a preview page or a file behind a login is not an image. Networks fetch media from a public address; if they cannot reach it, the post fails.
- Captions that only fit one network. A 600-character caption is fine on Facebook and LinkedIn and far too long for X.
- Networks that need media. Instagram and TikTok posts need an image or video, and YouTube needs a video. A text-only row aimed at those networks cannot be published there.
A good sheet removes each of these before the file ever leaves your computer.
The columns a clean sheet needs
Keep one row per post and one fact per column. These are the columns that matter for publishing:
| Column | What goes in it | Tip |
|---|---|---|
| date | The publishing date | Use YYYY-MM-DD (2026-11-03). It cannot be misread |
| time | The publishing time | 24-hour (14:30) avoids AM/PM mistakes |
| caption | The post text | Write the version for the most restrictive network you target, or split rows per network |
| accounts | Which networks or accounts | Use the names your scheduler recognises; keep a list in a second sheet |
| media | Public image or video links, or file names | One post, several items: separate them with a pipe (|) |
| alt | Alt text per image | Same order as the media column |
| link | The destination link | Tag it with UTM parameters before it goes in |
| first_comment | A comment posted right after the post | Useful for extra links or hashtags |
| title | An internal name | Helps you find the post later; not published |
Planning columns such as content pillar, owner, status and notes are worth keeping too. Put them to the right of the posting columns so you can see at a glance which columns the upload uses. Our free social media calendar template is laid out exactly this way.
Step by step: building the file
1. Start from a copy of the template
Download the scheduler’s own template rather than building headers from memory. Header names matter: a column called “Copy” may or may not be recognised as the caption. Keep the template’s header row exactly as it is.
2. Fix the date and time formats first
Before entering any posts, format the date column as text or as an ISO date (YYYY-MM-DD) and the time column as 24-hour time. If you paste dates from another document, check a few by hand. A single row with 11/03 where everyone meant 3 November is enough to publish a post a week early.
3. Agree whose time zone the sheet uses
Write it in the sheet’s first cell or the file name: “All times Europe/Berlin”. The safest rule for agencies is that every time in a client’s sheet is the client’s local time, because that is when their audience is awake. Our post on scheduling for clients in other time zones covers the traps around daylight saving changes.
4. Write captions per network, not per idea
If a post goes to Instagram, LinkedIn and X, you have two options: one row per network with a caption written for it, or one row with a caption short enough for all of them. One row per network is more work but reads better. Check lengths with the character counter before you paste, especially for X, where links and emoji are weighted differently.
5. Put media where networks can reach it
Use direct links to image or video files on a public address, or keep the files in one folder with exactly the names you put in the media column, if your scheduler lets you upload them with the sheet. Avoid spaces and accents in file names. Give every image alt text: a short description of what is in the picture, written for someone who cannot see it.
6. Tag every link
Add utm_source, utm_medium and utm_campaign to every link so the website analytics can attribute the visit. Google Analytics recommends always setting those three and notes that values are case sensitive, so “Instagram” and “instagram” become two sources (Google Analytics help). The free UTM builder lower-cases values for you.
7. Save in the right format
If you save as CSV, choose UTF-8 so accents and emoji survive. If you upload an Excel workbook, keep the posts on the first sheet; many tools only read the first one.
A pre-upload checklist
Run through this list before every upload. It takes two minutes and saves the clean-up afterwards.
- Every row has a date and a caption
- No dates in the past, and no dates you did not mean (sort by date and read down the column)
- Every row for Instagram or TikTok has media, and every YouTube row has a video
- Captions fit the strictest network on the row
- Every image has alt text, in the same order as the media
- Links are full addresses starting with https:// and carry UTM tags
- Media links open in a private browser window without signing in
- Planning-only columns (pillar, owner, notes) are to the right and will be ignored
- The file is saved as UTF-8 CSV or as .xlsx with posts on the first sheet
After the upload: what to review
Even a clean sheet deserves one look at the result. Open the month on the calendar and read it as the audience will:
- Are two similar posts landing on the same day?
- Did a campaign end up on a weekend when the client is closed?
- Does each network’s version read naturally, or was a caption written for one network forced onto another?
If the client approves posts, this is also the moment their review starts. Bulk uploading does not have to mean bulk publishing.
Doing this in PostRoost
PostRoost’s bulk upload takes CSV or Excel (.xlsx) files with the columns above: date, time, caption, accounts, media, alt, link, first_comment and title. Header names are matched loosely (“text”, “copy” or “message” all work as the caption). Dates can be 2026-11-03, 11/3/2026 (month first) or an Excel date cell, and times are read in the client’s own time zone, defaulting to 10:00.
Nothing is created until you confirm. Each row is checked for a valid date and time that is not in the past, accounts that exist, each network’s character limit and media requirements, valid links, and at most ten media items per post. You see every row with its status; rows with problems are listed with the reason and skipped, so you can fix them in the sheet. Posts are created as scheduled, or as pending approval when the client requires sign-off, so a bulk upload still goes through the approval workflow.
Media can be public links or file names: add the files in the second picker and PostRoost matches them by name (file uploads need media storage configured for your workspace). Bulk upload is included from the Essentials plan.





