A secret hidden image of chair 1. Find it at your peril. A secret hidden image of chair 2. Find it at your peril. A secret hidden image of chair 3. Find it at your peril. A secret hidden image of chair 4. Find it at your peril. A secret hidden image of chair 5. Find it at your peril.

Spreadsheet to Shortcode WP Plugin Documentation

This page explains what the “Ethan’s Spreadsheet to Shortcode” (or ES2S) WordPress plugin does, how to use it, and how its underlying pieces fit together. I originally hired a developer to build this for me, but rebuilt it from the ground up to be even more powerful in 2026.

View all of my free WordPress plugins and themes here.


1. What This Plugin Does

ES2S lets you upload a spreadsheet (Excel, CSV, or OpenDocument format) to your WordPress site, and then pull individual pieces of that spreadsheet into any post or page using a short piece of text called a shortcode.

In practice, this means you can keep a running spreadsheet on your computer โ€” like a wine list, an inventory, a directory, a price sheet, whatever you like โ€” and display specific rows from it on your website without retyping anything. When you update the spreadsheet and re-upload it, everywhere that data appears on the site updates too. If you can’t use a full database, this can help you out.

Nothing about this plugin is specific to any subject matter. However, the examples throughout this page use a wine list spreadsheet in discussion, simply because that’s a natural, easy-to-follow example. The same mechanism works for anything organized into rows and columns.


2. Preparing and Uploading a Spreadsheet

Supported file types

  • Excel workbooks: .xlsx and .xls
  • Comma-separated values: .csv
  • OpenDocument spreadsheets: .ods

Important: only the first tab is read

If your spreadsheet has multiple tabs (sheets) in it, only the first tab is ever read. Any other tabs are completely ignored, regardless of which tab happened to be open or “active” when you last saved the file. If you need the plugin to see certain data, that data needs to be on the first tab.

If you have multiple tabs with important data, I recommend copying them to separate spreadsheet files and uploading those separately.

How your spreadsheet should be laid out

The plugin expects a simple structure:

  • Row 1 is the header row. Whatever you type into row 1 of each column becomes the label that’s displayed alongside the data in that column.
  • Every row after that is a record. Row 2, row 3, row 4, and so on, each represent one “entry” โ€” one bottle of wine, one item, one person, whatever your spreadsheet is tracking.
  • Columns can go as far as you need. Once you pass column Z, spreadsheets continue with two-letter columns (AA, AB, AC, and so on). The plugin fully supports this โ€” you are not limited to 26 columns.

Uploading

From the ES2S settings page in your WordPress admin, use the “Upload a New Workbook” form. Once uploaded, the workbook is assigned a unique ID automatically (more on this in Section 5) and appears in the workbook table, ready to be referenced by a shortcode.

Uploading a new file does not overwrite anything you’ve uploaded before โ€” every upload is kept as its own separate workbook, unless you delete one yourself.


3. The Shortcode

The shortcode looks like this:

[es2s book="es2s-20260807-143012" row="3 A B C"]

Breaking that down:

  • book tells the plugin which uploaded spreadsheet to use. This is either the workbook’s ID (assigned automatically at upload), or a friendly alias you’ve set for it yourself (see Section 5).
  • row tells the plugin what to display. The first number is the row you want (row 3, in the example above), and everything after that is a list of which columns to pull from that row (columns A, B, and C, in the example above).

So the shortcode above says: “From this specific workbook, take row 3, and show me what’s in columns A, B, and C โ€” along with their column headers from row 1.”

You can list as many or as few columns as you like, and in any order:

[es2s book="es2s-20260807-143012" row="7 B AA D"]

That would show row 7’s columns B, AA (a two-letter column), and D, in that order.


4. How the Header Text Is Displayed โ€” and the Colon Trick

For every column you list in the shortcode, the plugin displays two things side by side: the header (from row 1 of that column) and the value (from the row you specified, in that same column).

Here’s the important part: the plugin does not add any punctuation or spacing between the header and the value on its own. If your header cell says Wine Color and the value cell says Red, the output will read:

Wine ColorRed

That’s almost certainly not what you want. To fix this, simply type the punctuation you want directly into the header cell in your spreadsheet. If row 1 of that column reads:

Wine Color:

…then the display becomes:

Wine Color: Red

This is a deliberate choice. It means you control exactly how each header looks (a colon, a dash, nothing at all, an em-dash, whatever fits your site’s style), simply by typing it into the spreadsheet itself. No two columns have to be punctuated the same way if you don’t want them to be.


5. Workbooks, IDs, and Aliases

Because you can upload more than one spreadsheet, the plugin needs a reliable way to tell them apart โ€” and a way for you to swap one out for another later without having to go back and edit every shortcode you’ve already written. This section explains how that works.

Workbook IDs

Every time you upload a file, it’s given a unique ID automatically, based on the date and time of the upload โ€” something like es2s-20260807-143012. You never have to type this yourself; it’s generated for you and shown in the workbook table, with a “Copy ID” button next to it for pasting into shortcodes.

Labels

Separately from the ID, each workbook also has a label โ€” a plain, editable name you choose, purely so you can recognize which workbook is which when looking at the admin table (for example, “Wine List โ€” August 2026”). Renaming the label doesn’t affect anything else; it’s just for your own reference.

Friendly Aliases

If typing out a long ID like es2s-20260807-143012 in every shortcode feels cumbersome, you can give a workbook a friendly alias instead โ€” a short, memorable name of your choosing, such as cellarlist. Once set, this:

[es2s book="cellarlist" row="3 A B C"]

…means exactly the same thing as this:

[es2s book="es2s-20260807-143012" row="3 A B C"]

A friendly alias must be unique across all your workbooks โ€” the plugin will warn you if you try to reuse one that’s already assigned somewhere else.

Legacy Aliases (Retiring an Old Workbook)

This is the part worth understanding carefully if you ever plan to replace a spreadsheet.

Say you uploaded a workbook, wrote a dozen shortcodes referencing it, and months later you want to upload a corrected or updated version of that same spreadsheet. You could just re-upload it โ€” but the new upload gets a brand-new ID, which means every shortcode still pointing at the old ID would break.

Instead, you can add the old workbook’s ID as a “legacy alias” on the new workbook. Once you’ve done that, any shortcode still referencing the old ID will automatically be redirected to the new workbook โ€” without you having to update a single shortcode.

To do this:

  1. Upload the new, replacement workbook.
  2. Open its “Manage” panel in the workbook table.
  3. Under “Legacy Aliases,” add the old workbook’s ID (and its own friendly alias, if it had one).
  4. If you’re ready, delete the old workbook entirely โ€” its data isn’t needed anymore, since the alias now points to the new file.

This aliasing step is always something you do deliberately โ€” the plugin never assumes one workbook should replace another on its own. You decide exactly which old references should now point to which new workbook.

Deleting a Workbook

When you delete a workbook that still has aliases pointing to it (a friendly alias, legacy aliases, or both), you’ll be shown what those aliases are and given the option to transfer them to another workbook before the deletion happens. If you choose a transfer target, that target workbook then inherits the deleted workbook’s ID and all its aliases as its own legacy aliases โ€” so shortcodes that were pointing at the deleted workbook, by any of its names, will resolve to the new one instead.

If you don’t choose a transfer target, those references will simply stop working, and any shortcode still using them will display a “Workbook not found” message on your site.


6. How the CSS Classes Work

This, in my opinion, is the most powerful part of the plugin, and the part I’m most proud of.

Every piece of what the shortcode displays is wrapped in an element with one or more CSS classes attached, so you have precise and granular control over how everything looks. This section walks through exactly what gets generated, using a concrete example.

Suppose your workbook’s ID is es2s-20260807-143012, and you use:

[es2s book="es2s-20260807-143012" row="3 A B"]

…where row 1, column A reads Wine:, row 3 column A reads Malbec 2019, row 1 column B reads Wine Color:, and row 3 column B reads Red. The plugin would generate something like this (simplified for readability):

<div class="es2s-post es2s-row3 es2s-book-es2s-20260807-143012">

  <p class="es2s-paragraph es2s-colA">
    <span class="es2s-descriptor es2s-cell-Wine">Wine:</span>
    <span class="es2s-entry es2s-cell-Malbec2019">Malbec 2019</span>
  </p>

  <p class="es2s-paragraph es2s-colB">
    <span class="es2s-descriptor es2s-cell-WineColor">Wine Color:</span>
    <span class="es2s-entry es2s-cell-Red">Red</span>
  </p>

</div>

Here is what each class means and where it comes from:

Class Where it comes from What it lets you target
es2s-post Always present The entire block for one shortcode
es2s-row3 The row number you specified Everything from this particular spreadsheet row, across your whole site
es2s-book-es2s-20260807-143012 The workbook’s ID Everything sourced from this particular workbook specifically
es2s-paragraph Always present Any individual header/value pair
es2s-colA, es2s-colB, etc. The column letter Everything from this particular column, across every row and every workbook
es2s-descriptor Always present Just the header text (e.g. “Wine Color:”)
es2s-entry Always present Just the value text (e.g. “Red”)
es2s-cell-Wine, es2s-cell-Red, etc. The actual text in that cell, cleaned up This exact piece of content, wherever it appears

Why the “es2s-cell-” classes look the way they do

CSS class names cannot start with a number, cannot contain spaces, and can’t contain most punctuation. Since a spreadsheet cell might contain absolutely anything โ€” a number, a date, an exclamation point, a blank cell โ€” the plugin can’t safely turn that content directly into a class name. Instead, it:

  1. Strips out spaces and any character that isn’t a letter, number, or hyphen.
  2. Adds the fixed prefix es2s-cell- in front of whatever’s left.

So a cell reading 2020 Special!! Cuvรฉe becomes the class es2s-cell-2020SpecialCuve โ€” safe to use in CSS no matter what the original cell contained, because the prefix guarantees the class always starts with a letter.

You don’t have to worry about a spreadsheet cell being too long for a CSS class, either. As I found out, CSS classes can be really, really long.

Putting it together: styling a specific value in a specific column

This is the reason for all that granularity. Say you want every wine whose “Wine Color” column says “Red” to actually display in red text โ€” but you don’t want to accidentally also turn other columns red, if they happen to contain unrelated cells that also say “Red.” Because the value class (es2s-cell-Red) will always sit inside the column class (es2s-colB), you can combine them in your CSS:

p.es2s-colB .es2s-cell-Red {
    color: #a10000;
}

That rule only applies to cells with the text “Red” and that are specifically in column B โ€” nowhere else.

If you wanted that styling to apply only within one specific workbook (say, you have two wine lists and only want this rule on one of them), you could narrow it further:

.es2s-book-es2s-20260807-143012 p.es2s-colB .es2s-cell-Red {
    color: #a10000;
}

There are so,ย so many different possibilities with this depending on your creativity and the subject of your spreadsheet. There is a ton of power here.


7. Saved Shortcode Presets

If you find yourself typing the same column list over and over โ€” for example, always displaying columns A, B, and C for every wine entry you post โ€” you can save that pattern as a preset on the settings page, under “Saved Shortcode Presets.”

A preset stores only the column pattern (like A B C), not a workbook. This is intentional: presets are meant to survive you swapping out one workbook for another later (see Section 5), so a preset you set up once keeps working even after the underlying spreadsheet changes.

To use a saved preset, fill in the workbook (its ID or friendly alias) and the row number you want next to the preset in the table, and click “Copy Shortcode” โ€” the complete shortcode is copied to your clipboard, ready to paste into a post.


8. Quick Troubleshooting

  • “Workbook not found.” โ€” The book value in your shortcode doesn’t match any current workbook ID, friendly alias, or legacy alias. Double-check for typos, or confirm the workbook wasn’t deleted without its aliases being transferred elsewhere.
  • “No row specified.” / “No column specified.” โ€” The row attribute needs a row number followed by at least one column letter, separated by spaces, e.g. row="3 A B".
  • Header and value run together with no space or punctuation. โ€” See Section 4; add the punctuation you want directly into the header cell in your spreadsheet.
  • A tab in my spreadsheet isn’t showing up. โ€” Only the first tab is ever read. Move the data you need to the first tab.
  • I uploaded a new version of a spreadsheet and my old shortcodes broke. โ€” See Section 5 on legacy aliases; add the old workbook’s ID as a legacy alias on the new one.

If you have any questions, please contact me and I’ll get back to you as best as I can, keeping the disclaimer in mind.