Auto-generate RAMS PDFs from a simple Google Form: a 60‑minute setup for small contractors featured image
How-to Guides

Auto-generate RAMS PDFs from a simple Google Form: a 60‑minute setup for small contractors

TrainAR Team 1 month ago 6 min read

Auto-generate RAMS PDFs from a simple Google Form: a 60‑minute setup for small contractors

Category: How-to Guides Niche: RAMS automation, Google Forms, Google Docs, Apps Script

Site manager fills a Google Form while a RAMS PDF appears in Google Drive on a laptop

Contents

Quick answer

You’ll create a short Google Form for each job, send responses into a Google Sheet, use a Google Doc as the RAMS template with {{placeholders}}, and an Apps Script will auto‑create a filled PDF in the right Drive folder whenever the form is submitted. It cuts paperwork time, keeps a consistent layout, and gives you a PDF you can email to clients or attach to work orders.

What you’ll set up

  • A Google Doc RAMS template that uses placeholders like {{Company name}}, {{Job address}}, {{Supervisor}}, {{Sign-off name}}.
  • A Google Form (mobile friendly) to capture task, hazards, controls, PPE, plant, COSHH references and sign‑off details.
  • A Google Sheet to store the responses.
  • An Apps Script that copies the template, replaces placeholders and saves a PDF into a “Job RAMS” Drive folder per job.

Flowchart: Form to Sheet to Doc template to PDF to email

Before you start: UK safety note

HSE requires you to assess risk; if you employ 5 or more people you must record significant findings. Method statements are not generally a legal requirement, but HSE recognises them as good practice for communicating the safe system of work and they are required in writing for demolition/dismantling. Useful pages: HSE risk assessment template and steps and the construction admin and method statement guidance on HSE construction.

If you’re new to RAMS, read our primer: RAMS for UK construction: simple steps, free template and how to brief your team.

Step-by-step: build the RAMS generator

1) Create the RAMS Doc template

  • In Google Docs, create sections you always use: Scope, Responsibilities, Hazards, Controls, PPE, Plant, Emergency, COSHH, Sign‑off.
  • Insert placeholders in double curly braces, matching your Sheet headers later: {{Company name}}, {{Job address}}, {{Task}}, {{Hazards}}, {{Controls}}, {{PPE}}, {{Plant}}, {{Supervisor}}, {{Sign-off name}}, {{Date}}.
  • Grab the template file ID from its URL (between /d/ and /edit).

2) Build a short Google Form

Suggested fields:

  • Company name, Job address, Task summary
  • Hazard checklist with “Other” free‑text
  • Controls text area (method steps)
  • PPE, Plant/Tools, COSHH refs or SDS links
  • Supervisor name, Date, Sign‑off name and email

Keep it quick so operatives can complete on a phone. Use Response validation where helpful (e.g., email format).

3) Link the Form to a Sheet

  • In the Form, go to Responses > Link to Sheets and create a new spreadsheet.
  • Note the tab name (usually “Form Responses 1”).

4) Add the Apps Script to generate PDFs

Open the Sheet > Extensions > Apps Script and paste this working script. Update TEMPLATE_ID, DEST_FOLDER_ID and SHEET_NAME.

const CONFIG = {
  TEMPLATE_ID: 'PUT_YOUR_DOC_TEMPLATE_ID_HERE',
  DEST_FOLDER_ID: 'PUT_YOUR_DEST_FOLDER_ID_HERE',
  SHEET_NAME: 'Form Responses 1',
  PDF_LINK_COLUMN_NAME: 'PDF URL',
  TIMEZONE: Session.getScriptTimeZone()
};

function escRe(s){return String(s).replace(/[.*+?^${}()|[\]\\]/g,'\\$&');}
function ensureHeaderColumn_(sheet, headerName){
  const headers = sheet.getRange(1,1,1,sheet.getLastColumn()).getValues()[0]||[];
  let col = headers.indexOf(headerName)+1;
  if(col===0){sheet.getRange(1,sheet.getLastColumn()+1).setValue(headerName);col=sheet.getLastColumn();}
  return col;
}
function rowToObject_(headers,row){const o={};headers.forEach((h,i)=>o[h]=row[i]);return o;}

function generatePdfFromData_(templateId, dataObj, destFolderId, fileNameNoExt){
  const destFolder = DriveApp.getFolderById(destFolderId);
  const tempCopy = DriveApp.getFileById(templateId).makeCopy(fileNameNoExt+' (tmp)', destFolder);
  try{
    const doc = DocumentApp.openById(tempCopy.getId());
    const body = doc.getBody();
    Object.keys(dataObj).forEach(key=>{
      const val = dataObj[key]==null?'':String(dataObj[key]);
      body.replaceText('\\{\\{'+escRe(key)+'\\}\\}', val);
    });
    doc.saveAndClose();
    const pdfBlob = tempCopy.getAs(MimeType.PDF).setName(fileNameNoExt+'.pdf');
    const pdfFile = destFolder.createFile(pdfBlob);
    return pdfFile;
  } finally {
    tempCopy.setTrashed(true);
  }
}

function generateAllPdfs(){
  const sheet = SpreadsheetApp.getActive().getSheetByName(CONFIG.SHEET_NAME);
  if(!sheet) throw new Error('Sheet not found');
  const lastRow = sheet.getLastRow(), lastCol = sheet.getLastColumn();
  if(lastRow<2) return;
  const headers = sheet.getRange(1,1,1,lastCol).getValues()[0];
  const rows = sheet.getRange(2,1,lastRow-1,lastCol).getValues();
  const pdfCol = ensureHeaderColumn_(sheet, CONFIG.PDF_LINK_COLUMN_NAME);
  rows.forEach((row,i)=>{
    const r = i+2; const existing = sheet.getRange(r,pdfCol).getValue(); if(existing) return;
    const obj = rowToObject_(headers,row);
    const stamp = Utilities.formatDate(new Date(), CONFIG.TIMEZONE, 'yyyy-MM-dd HHmm');
    const base = (obj['Job address']||obj['Task']||'RAMS');
    const pdf = generatePdfFromData_(CONFIG.TEMPLATE_ID,obj,CONFIG.DEST_FOLDER_ID, base+' - '+stamp);
    sheet.getRange(r,pdfCol).setValue(pdf.getUrl());
  });
}

function onFormSubmit(e){
  const sheet = e.range.getSheet(); if(sheet.getName()!==CONFIG.SHEET_NAME) return;
  const dataObj={}; Object.keys(e.namedValues).forEach(k=>{const v=e.namedValues[k];dataObj[k]=Array.isArray(v)?v[0]:v;});
  const stamp = Utilities.formatDate(new Date(), CONFIG.TIMEZONE, 'yyyy-MM-dd HHmm');
  const base = (dataObj['Job address']||dataObj['Task']||'RAMS');
  const pdf = generatePdfFromData_(CONFIG.TEMPLATE_ID,dataObj,CONFIG.DEST_FOLDER_ID, base+' - '+stamp);
  const pdfCol = ensureHeaderColumn_(sheet, CONFIG.PDF_LINK_COLUMN_NAME);
  sheet.getRange(e.range.getRow(), pdfCol).setValue(pdf.getUrl());
}
  • Set the trigger: Apps Script > Triggers > Add Trigger > onFormSubmit > From spreadsheet > On form submit.
  • Test with a dummy submission. Check the PDF lands in your Drive folder and the URL is written back to the Sheet.

5) File naming and job folders

  • Create a Drive parent folder called “Job RAMS”. For each new job, create a subfolder “Job address – RAMS”. Point DEST_FOLDER_ID to the right subfolder so each job keeps its own PDFs.
  • If you use a job number, include it at the start of the PDF file name for easy sorting, e.g., 241007‑004‑RAMS‑Kitchen‑refit.pdf.

6) Email the PDF and store approvals

Add this helper to email a copy to your supervisor or client:

function sendPdf_(to, subject, body, pdfFile){
  if(!to) return; GmailApp.sendEmail(to, subject, body, {attachments:[pdfFile.getAs(MimeType.PDF)]});
}

Call it from onFormSubmit, for example using the {{Sign-off email}} field.

Add approvals and version control

  • Approvals in Gmail: keep it simple. When a RAMS is generated, email the PDF to an approver and ask them to reply “Approved”. File the thread in a label like RAMS/Approved.
  • Version numbering: include v1, v2 in the Doc title and a {{Version}} field in the Form.
  • Change log: add a small table in your Doc template to note date, editor, and a one‑line change reason.

Make it easy on site: QR codes and WhatsApp

  • Print a QR code that links to the Form so operatives can scan and complete on site. See: Toolbox talk attendance QR code.
  • If you run WhatsApp Business, paste the Form link in a canned reply like “Please complete the RAMS form before starting.” Pair this with your induction messages.

Troubleshooting

  • Placeholders didn’t replace: headers must exactly match the {{placeholders}} (case sensitive). Check brackets.
  • Script errors: first run needs authorisation for Drive, Docs, Sheets (and Gmail if emailing). Re‑run and accept.
  • Multiple lines not appearing: long text areas are fine, but keep the Doc template styles simple.
  • Missing PDFs: confirm DEST_FOLDER_ID is a folder ID, not a file ID; make sure you have edit permission.

FAQ

Risk assessment is a legal duty and must be suitable and sufficient. Method statements aren’t generally required by law but are common and often requested by clients. See HSE’s guidance and risk assessment template: HSE risk assessment and [Construction admin](https://www.hse.go