Build a custom sidebar data-entry form
Capture structured input inside Northwind's Sheets — sidebar UI bound to the workbook.
Published Jul 3, 2025
Typing straight into a spreadsheet is fast until it isn’t. At Northwind, the projects log kept drifting: dates entered in the wrong column, the timestamp forgotten, a client name spelled three different ways. The data was right there in the grid, so people skipped the discipline a form would have forced on them.
A sidebar form fixes that without leaving the sheet. It opens in a panel beside the grid, takes a small set of required fields, and appends a clean, consistently shaped row every time. The person entering data never touches a cell directly, so the columns stay in order and the timestamp is never missed.
What you’ll need
- A Google Sheet whose first tab is the log you want to append to. The script writes three columns in this order: timestamp, client, project — so the sheet should have headers to match in row 1.
- An HTML file named
Sidebarin the same Apps Script project (created with File > New > HTML file). - No add-on, no deployment — the sidebar runs inside the bound script, so anyone who can edit the sheet can open it.
The sidebar HTML (Sidebar.html)
<!-- A minimal form. "required" makes the browser block an empty submit. -->
<form id="f">
<label>Client <input name="client" required></label>
<label>Project <input name="project" required></label>
<button>Add</button>
</form>
<script>
// Intercept the submit so the page never reloads.
document.getElementById('f').addEventListener('submit', (e) => {
e.preventDefault();
// Turn the form fields into a plain { client, project } object.
const data = Object.fromEntries(new FormData(e.target));
// Call the server-side addRow function with that object.
google.script.run.addRow(data);
// Clear the fields so the next entry starts fresh.
e.target.reset();
});
</script>
The Apps Script
// The tab the form appends to. The first sheet in the workbook.
const TARGET_SHEET_INDEX = 0;
/**
* Runs when the spreadsheet opens. Adds a Northwind menu so anyone
* can launch the sidebar without opening the script editor.
*/
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Northwind')
.addItem('Add row…', 'showSidebar')
.addToUi();
}
/**
* Opens the Sidebar.html file as a panel beside the grid.
*/
function showSidebar() {
const html = HtmlService.createHtmlOutputFromFile('Sidebar')
.setTitle('Add a row');
SpreadsheetApp.getUi().showSidebar(html);
}
/**
* Called from the sidebar form. Appends one clean row with a
* timestamp, so the columns stay consistent on every entry.
*/
function addRow(data) {
// Guard: ignore an empty or malformed payload.
if (!data || !data.client || !data.project) return;
// appendRow always writes after the last row — no row-counting needed.
SpreadsheetApp.getActive()
.getSheets()[TARGET_SHEET_INDEX]
.appendRow([new Date(), data.client, data.project]);
}
How it works
onOpenruns automatically when the workbook is opened and adds a Northwind menu with a single Add row… item.- Choosing that item calls
showSidebar, which loadsSidebar.htmland docks it as a panel on the right of the spreadsheet. - The form has two required fields. The browser blocks an empty submit before the script ever sees it.
- On submit, the page’s script cancels the default reload, collects the fields
into a
{ client, project }object, and hands it to the server withgoogle.script.run.addRow(data). addRowruns on the Apps Script side. It bails out if either field is missing, then appends a row of[timestamp, client, project]to the first tab — so the date is always recorded and the columns never drift.- The form resets, ready for the next entry, while the sidebar stays open.
Example run
A user opens the sheet, picks Northwind > Add row…, and types into the panel:
| Field | Value |
|---|---|
| Client | Atlas Foods |
| Project | Q3 rebrand |
After clicking Add, a new row appears at the bottom of the first tab:
| Timestamp | Client | Project |
|---|---|---|
| 2025-07-03 09:14:22 | Atlas Foods | Q3 rebrand |
The fields clear, and the next entry can go straight in without reaching for the mouse.
Run it
This is an on-demand tool, so there is no trigger to schedule:
- Paste the Apps Script into the bound project and create the
SidebarHTML file alongside it. - Reload the spreadsheet so
onOpenruns and the Northwind menu appears. - Choose Northwind > Add row… and approve the authorisation prompt the first time.
- Enter a client and project, then click Add.
Watch out for
- The menu only appears after a reload.
onOpenruns when the workbook opens, so the first time you add the code you must refresh the tab to see it. google.script.runis fire-and-forget here. The form resets immediately without waiting for the server. If you want a “saved” confirmation, add a.withSuccessHandler()callback before.addRow(data).- Column order is fixed in
addRow. If you add a field to the form, add it to theappendRowarray too, or the new value will land in the wrong column. - The sidebar is roughly 300px wide and cannot be resized. Keep the form short; it is built for quick structured entry, not long records.
- Anyone who can edit the sheet can open the form and append rows. There is no per-user permission layer — the sidebar inherits the spreadsheet’s sharing.
Related
Build a branded approval interface
Approve Northwind requests through a custom UI — clients click, decision is logged.
Updated Nov 8, 2025
Build an interactive quiz or assessment app
Run Northwind tests with scoring and feedback — questions in a Sheet, results in another.
Updated Nov 4, 2025
Build a multi-page web app with routing
Structure a real Northwind app across views — query-param routing, shared layout.
Updated Oct 31, 2025
Build a form-to-PDF web service
Convert Northwind form submissions to PDFs on the fly — POST in, PDF out.
Updated Oct 27, 2025
Build an expiring secure-download generator
Issue time-limited Northwind links via a web app — token in URL, server-side check.
Updated Oct 23, 2025