2.7.1 • Public • Published


The microplate package is built for parsing microtiter plate information from Excel sheets, validating the contents of plate layouts, and saving plate layouts into Excel or CSV files.

Layout formats

A spreadsheet with one or more plate layouts will be formatted like this:

plate-1  1       2		  3		...
A	     item-1  item-2
B                         item-3

plate-2  1      2		  3		...

Alternatively, the spreadsheet can be in tabular format, which also allows for providing multiple columns of data:

plate-1   A1        item-1      5
plate-1   A2        item-2     15
plate-1   B3        item-3     10
.        .
.        .
.        .

The plate layout parser will return a list of all layouts it detects.


You can install this package with NPM:

npm install microplate


The examples in this section contain ECMAScript 2016 (ES7) code. Use equivalent ECMAScript 5 code where necessary.


A sheet object is created from either an Excel sheet, converted CSV file, or other 2D-array sources. They are the intermediary format between files and plate layouts. For different ways to load sheets from Excel files, read Working with Excel files.

Parsing and validating plate layouts

Plate layouts are processed in three stages:

  1. Reading a workbook and selecting a sheet
  2. Parsing the sheet into a layout
  3. Validating the layout's contents

Parsing step

In this example we are parsing a grid-based sheet we've built from an array:

import {Sheet, PlateLayout} from 'microplate';

let sheet = new Sheet([
    ['platename', 1, 2, 3],
    ['A', 'item1', 'item2', 'item3'],
    ['B', 'item1', 'item2', 'item3'],

let layouts = PlateLayout.parse(sheet, {
    default: 'name',
    converters: {
        name: 'string'

PlateLayout.parse() always returns an array, because both grid and tabular formats support multiple plates. The converters option is a dictionary for enforcing types on values. default is only used with grid layouts.

Possible converters are:

name description
number numeric value
string string value
number[] array of numbers (comma separated list)
string[] array of strings (comma separated list)
string(position) well position

A list-based plate layout is processed like so:

let sheet = new Sheet([
    ['plate', 'position', 'name', 'score value'],
    ['platename', 'A1', 'item1', 5],
    ['platename', 'A2', 'item2', 9],
    ['platename', 'A3', 'item3', 11],
    ['platename', 'B1', 'item1', 7],
    ['platename', 'B2', 'item2', 9],
    ['platename', 'B3', 'item3', 15],

let layouts = PlateLayout.parse(sheet, {
    aliases: {
    	'score': ['score value']
    required: ['name', 'score'],
    converters: {
    	name: 'string',
    	score: 'number'

The validation here makes use of aliases and required option values, for header name aliases and required columns respectively. The full .parse() function syntax:

PlateLayout.parse(sheet: Sheet, {
    default?: string,
    aliases?: {[name:string]: string[]},
    converters?: {[name:string]: string},
    required?: string[]
}): PlateLayout[]

Validation step

To validate each position in a plate layout, use PlateLayout.prototype.validate().

// dummy lookup function
function lookupItemByName(name) {
    return Promise.resolve({name: name}) 

try {
    let validatedLayout = layouts[0].validate({
        name: lookupItemByName
} except(e) {
    // errors grouped by well position.

The full .validate() function syntax:

    validators: {[name:string]: (any) => Promise}, 
    parallel: boolean): Promise<PlateLayout>

Parsing and validating tables

In addition to plate layouts, the package contains a Table class. A table works just like a plate layout, with the difference that there are no well positions, but rows.

let sheet = new Sheet([
    ['id', 'name'],
    [1, 'foo'],
    [2, 'bar']

let table = Table.parse(sheet);

try { // validation
    table = await table.validate({id: lookupByIdFunction});
} except (e) { 
    console.log('validation errors:', e)

for(let row of table) {

If parallel is false, the validator functions in Table functions will receive two arguments. The second argument will be an array with all previously processed rows. This is useful when importing a table where validation depends on values in previous rows.

You can create a Sheet from a Table like so:

let sheet = new Table([
    {id: 2, name: 'bar'},
    {id: 3, name: 'baz'}

Working with Excel files

The microplate package has some features that aid with import and export to Excel using xlsx. These examples here are for command-line use.

import fs from 'fs';
import {Workbook} from 'microplate';

let file = fs.readFileSync('./example.xlsx');
let workbook = Workbook.fromFile(file);

console.log(workbook.sheetNames()); // ['Sheet 1', 'Sheet 2']

let sheet1 = workbook.sheet('Sheet 1');
console.log(sheet1.name); // 'Sheet 1'

for(let sheet of workbook) { /* iterates through all sheets in a workbook */ }

let workbook2 = new Workbook({foo: new Sheet()}); // initialize a new Workbook.

You can also load a workbook from an <input/> in the browser. First, add a file input to your page:

<input type="file" accept=".xlsx" />

Now you can load files like so:

let input = document.querySelector('input[type=file]');

input.addEventListener('change', function () {
    if(this.files.length) {
        let fileReader = new FileReader();
        fileReader.onload = (e) => {	
            let workbook = Workbook.fromFile(e.target.result);


To save a workbook in the browser, use e.g. filesaver.js :

import {saveAs} from 'filesaver.js';
let wb = new Workbook({foo: new Sheet()}); // initialize a new Workbook.
saveAs(wb.toBlob(), 'foo.xlsx');    

For more information, read Using files from web applications on MDN.

Package Sidebar


npm i microplate

Weekly Downloads






Last publish


  • lyschoening