Sheetline documentation1.x
Developers

Adding columns

Add your own fields to the Bulk Editor with the sheetline_columns filter: the column format, value types, validation, permissions and sorting.

Any post field can become a Bulk Editor column with the sheetline_columns filter. Put the code in a small custom plugin or your child theme's functions.php. Columns you add get everything the built-in ones have: keyboard editing, highlighted unsaved changes, errors on their cell, Screen Options, and with Sheetline Pro bulk changes, undo and CSV export and import.

A first column

// A "Subtitle" text column for posts, stored in post meta.
add_filter( 'sheetline_columns', function ( $columns, $post_type ) {
	if ( 'post' !== $post_type ) {
		return $columns;
	}
	$columns['subtitle'] = array(
		'label' => 'Subtitle',
		'group' => 'Extras',
		'type'  => 'text',
		'get'   => function ( WP_Post $post ) {
			return (string) get_post_meta( $post->ID, 'subtitle', true );
		},
		'set'   => function ( \Extendiment\Sheetline\Draft $draft, $value ) {
			$draft->meta( 'subtitle', sanitize_text_field( $value ) );
		},
		'sort'  => array( 'meta' => 'subtitle' ),
	);
	return $columns;
}, 10, 2 );

The key (subtitle) must be unique. The filter runs once per post type, with the post type as its second argument, so each Bulk Editor can have its own columns.

Setters record, they don't save

A column's set gets a Draft: the post's pending changes. Record the new value there and Sheetline writes everything once, after checking every cell of the post:

Draft method What it does when the post is saved
$draft->field( 'post_title', $value ) Sets a wp_update_post() field (unslashed)
$draft->meta( $key, $value ) Updates post meta ('' or null deletes the key)
$draft->terms( $taxonomy, $ids ) Replaces the post's terms of a taxonomy
$draft->before( fn( $id ) => … ) Runs before the post is updated
$draft->after( fn( $id ) => … ) Runs after the post is updated

$draft->post is the post as loaded, and $draft->get( 'post_status' ) a field as it will be saved. Never write to the database in set yourself: Sheetline Pro calls the same setters to preview bulk changes and imports without saving.

The column format

Key Required What it is
label yes Shown in the header and in Screen Options
type yes How the value is shown and edited (see below)
get yes function ( WP_Post $post ) returning the value to edit
set yes function ( Draft $draft, $value ) recording a new value
group no Groups related columns (default "Other")
options for select and terms value => label pairs, or a function returning them (called only when needed)
applies no function ( WP_Post $post ) returning false where the field doesn't exist (the cell shows a dash)
can no function ( WP_Post $post ) returning false where the current user may not change it (the cell is read-only). Sheetline already checks edit_post for every post
hidden no true to hide the column until switched on in Screen Options
sort no Makes it sortable: a WP_Query orderby value (e.g. 'title'), or array( 'meta' => 'my_key', 'num' => true )
bulk no false keeps the column out of Sheetline Pro's bulk changes

Types

Type Value Edited with
text string a text box
longtext HTML string a larger text box over the cell
number number as a string a text box
date Y-m-d string, '' for none a date picker
datetime Y-m-d H:i string a date and time picker
select one of the options keys a dropdown
bool 'yes' or 'no' a Yes/No dropdown
terms array of term IDs a checkbox list of the options
image attachment ID as a string, '' for none the media library
images array of attachment IDs the media library, several in order
readonly string shown, not editable

Values arrive in set as the grid sends them: strings, or arrays of IDs for terms and images. Sanitize them as you would any input.

Refusing a value

Throw an exception with a message for the editor. It appears under the cell in red, and that post isn't saved:

'set' => function ( \Extendiment\Sheetline\Draft $draft, $value ) {
	$value = trim( (string) $value );
	if ( '' !== $value && ! preg_match( '/^\d{4}$/', $value ) ) {
		throw \Extendiment\Sheetline\Columns::invalid( 'Enter a year, such as 2026.' );
	}
	$draft->meta( 'year', $value );
},

Columns::invalid() returns an InvalidArgumentException; any InvalidArgumentException works.

Helpers

Extendiment\Sheetline\Columns has the helpers the built-in columns use:

  • Columns::option( $value, $options ): one of the options' keys; refuses anything else.
  • Columns::bool( $value ): true for "yes", "1", "true" or "on".
  • Columns::integer( $value ), Columns::number( $value ): a whole number, or any number (a comma works as the decimal point).
  • Columns::date( $value ), Columns::datetime( $value ): a valid date, or date and time, in the formats above.
  • Columns::term_options( $taxonomy ): a taxonomy's terms as ID => 'Parent › Child', ready for options.
  • Columns::term_ids( $value, $taxonomy ): the IDs, each an existing term of the taxonomy.
  • Columns::statuses(), Columns::authors( $post_type ): the status and author options the grid uses.
// A taxonomy as a terms column, for a "book" post type.
add_filter( 'sheetline_columns', function ( $columns, $post_type ) {
	if ( 'book' === $post_type ) {
		$columns['series'] = array(
			'label'   => 'Series',
			'type'    => 'terms',
			'options' => fn() => \Extendiment\Sheetline\Columns::term_options( 'series' ),
			'can'     => fn() => current_user_can( get_taxonomy( 'series' )->cap->assign_terms ),
			'get'     => fn( $p ) => wp_get_object_terms( $p->ID, 'series', array( 'fields' => 'ids' ) ),
			'set'     => fn( $d, $v ) => $d->terms( 'series', \Extendiment\Sheetline\Columns::term_ids( $v, 'series' ) ),
		);
	}
	return $columns;
}, 10, 2 );

Taxonomies registered for a post type with show_ui already get a column of their own, so you only need this for something special.

Where the column goes

Columns appear in the array's order. Adding a key puts the column at the end; to place it elsewhere, rebuild the array:

add_filter( 'sheetline_columns', function ( $columns ) {
	$at  = array_search( 'title', array_keys( $columns ), true ) + 1;
	$new = array( 'kicker' => array( /* … */ ) );
	return array_slice( $columns, 0, $at, true ) + $new + array_slice( $columns, $at, null, true );
} );

Sheetline Pro adds its columns at priority 5, so columns added at the default priority 10 come after them.