← Back to Quote & Invoice Tool

🔗 Google Sheets — One-Click Setup

3 minutes. No coding. Your invoices auto-save to a Google Sheet forever.

1 Make a Copy of the Template Sheet

We've built a ready-to-use Google Sheet with 4 tabs, demo data, and the sync script pre-installed. You just need to make a copy.

💡 What's inside? The template comes with:
  • Products tab — 5 sample products with prices
  • Customers tab — 3 sample customers
  • Profiles tab — 1 sample business profile
  • Invoices tab — empty, ready to receive your invoices
  • Apps Script already installed (no pasting needed)

Don't want the template? You can also download blank CSV files and create your own sheet.

2 Copy Your Publish URLs

For each tab in your copied sheet, publish it as CSV. This gives the tool read-only access to your products, customers, and profiles.

For each tab (Products, Customers, Profiles):
File → Share → Publish to web → Choose Comma-separated values (.csv) → Publish → Copy the URL
Tab NamePaste URL into Tool Field
Products https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/pub?gid=PRODUCTS_GID&output=csv
Customers https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/pub?gid=CUSTOMERS_GID&output=csv
Profiles https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/pub?gid=PROFILES_GID&output=csv

Each tab gets its own URL. Paste all three into the Data Source panel of the Quote & Invoice tool.

3 Deploy the Sync Script (One Click)

The Apps Script is already in your sheet from the template. You just need to deploy it once:

  1. In your copied Google Sheet, click Extensions → Apps Script
  2. You'll see the pre-loaded script. Click Deploy → New deployment
  3. Click the ⚙️ gear → Select Web app
  4. Set Execute as: Me and Who has access: Anyone
  5. Click Deploy → Authorize (Google will ask once) → Copy the URL

Your Apps Script URL will look like:

URLhttps://script.google.com/macros/s/AKfycbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/exec
🔒 Is "Anyone" safe? Your URL contains a long random ID. Only people who have the exact URL can access it. It's like a password — keep it private.
4 Paste URLs into the Tool

Open the Data Source panel in the Quote & Invoice tool and paste:

FieldPaste
Products Sheet URLCSV publish URL from Products tab
Customers Sheet URLCSV publish URL from Customers tab
Profiles Sheet URLCSV publish URL from Profiles tab
Apps Script Web App URLURL from Step 3's Deploy

Click Save & Sync Now. From now on:

📋 The Sync Script (for reference)

The template already has this script installed. This is here only if you're building your own sheet from scratch.

JavaScript// ═══════════════════════════════════════════════════
// Tender84 Quote & Invoice Tool — Sheet Sync Script
// ═══════════════════════════════════════════════════

var SHEETS = {
  products:  'Products',
  customers: 'Customers', 
  profiles:  'Profiles',
  invoices:  'Invoices'
};

// GET: Return invoices as JSON
function doGet(e) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEETS.invoices);
  var data = sheet.getDataRange().getValues();
  if (data.length < 2) return json({ invoices: [] });
  
  var headers = data[0];
  var invoices = [];
  for (var i = 1; i < data.length; i++) {
    var row = {};
    for (var j = 0; j < headers.length; j++) row[headers[j]] = data[i][j] || '';
    if (row.Number) invoices.push(row);
  }
  return json({ invoices: invoices, count: invoices.length });
}

// POST: Append invoice row
function doPost(e) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEETS.invoices);
  var payload = JSON.parse(e.postData.contents);
  var invoices = Array.isArray(payload) ? payload : [payload];
  var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
  
  invoices.forEach(function(inv) {
    var row = [];
    for (var j = 0; j < headers.length; j++) {
      var key = headers[j];
      row.push(inv[key] !== undefined ? inv[key] : '');
    }
    sheet.appendRow(row);
  });
  
  return json({ success: true, added: invoices.length });
}

function json(obj) {
  return ContentService.createTextOutput(JSON.stringify(obj))
    .setMimeType(ContentService.MimeType.JSON);
}
📥 Download Demo CSV Files

These are the exact CSV files pre-loaded in the template. Use them if you prefer to start from scratch with your own sheet.

Need help? WhatsApp Support