Free Job Alert: Latest Jobs | Admit Cards | Results

Bill Maker Online – Free Invoice Bill Generator

Invoice Bill Maker

Online work, Photoshop/photo work, lamination, print and custom service bills.
5in x 7in Canvas
Logo

Bill Items

Saved Bill List

Dynamic Bill File

Preview updates automatically. Canvas size is 5 inch width x 7 inch height.
Logo
' : 'Logo'; if (state.logoData) { var image = new Image(); image.onload = function () { state.logoImage = image; renderCanvas(); }; image.src = state.logoData; } renderCanvas(); } function addItem(name, qty, rate) { state.items.push({ name: name || '', qty: qty || 1, rate: rate || 0 }); renderItems(); renderCanvas(); } function removeItem(index) { state.items.splice(index, 1); if (!state.items.length) { addItem('Online Form Work', 1, 50); return; } renderItems(); renderCanvas(); } function renderItems() { itemsWrap.innerHTML = ''; state.items.forEach(function (item, index) { var row = document.createElement('div'); row.className = 'bill-item-row'; row.innerHTML = '' + '' + '' + ''; var inputs = row.querySelectorAll('input'); inputs[0].addEventListener('input', function () { item.name = this.value; renderCanvas(); }); inputs[1].addEventListener('input', function () { item.qty = Number(this.value); renderCanvas(); }); inputs[2].addEventListener('input', function () { item.rate = Number(this.value); renderCanvas(); }); row.querySelector('button').addEventListener('click', function () { removeItem(index); }); itemsWrap.appendChild(row); }); } function billData() { var subtotal = state.items.reduce(function (sum, item) { return sum + (Number(item.qty || 0) * Number(item.rate || 0)); }, 0); var discount = Number(fields.discount.value || 0); var taxable = Math.max(subtotal - discount, 0); var taxPercent = Number(fields.taxPercent.value || 0); var taxAmount = taxable * taxPercent / 100; var total = taxable + taxAmount; var paid = Number(fields.paidAmount.value || 0); return { id: state.selectedId || String(Date.now()), shopName: fields.shopName.value || shop.name, shopPhone: fields.shopPhone.value || '', shopAddress: fields.shopAddress.value || '', logoData: state.logoData, billNo: fields.billNo.value || nextBillNo(), date: fields.billDate.value || today(), template: fields.billTemplate.value || 'classic', customerName: fields.customerName.value || 'Walk-in Customer', customerAddress: fields.customerAddress.value || '', customerMobile: fields.customerMobile.value || '', discount: discount, taxPercent: taxPercent, taxAmount: taxAmount, paid: paid, paymentMode: fields.paymentMode.value || 'Cash', subtotal: subtotal, total: total, balance: Math.max(total - paid, 0), note: fields.billNote.value || 'Thank you for your business.', items: JSON.parse(JSON.stringify(state.items)) }; } function palette(template) { if (state.printMode === 'bw') { return { brand: '#111111', accent: '#333333', soft: '#ffffff', line: '#111111', ink: '#111111', muted: '#333333', tableAlt: '#f7f7f7', footer: '#111111' }; } var palettes = { classic: {brand:'#8b3a1b', accent:'#f97316', soft:'#fff7ed', line:'#dbe3ee', ink:'#111827', muted:'#64748b', tableAlt:'#f8fafc', footer:'#8b3a1b'}, modern: {brand:'#0f766e', accent:'#14b8a6', soft:'#ecfdf5', line:'#ccfbf1', ink:'#102a43', muted:'#486581', tableAlt:'#f0fdfa', footer:'#0f766e'}, compact: {brand:'#1d4ed8', accent:'#60a5fa', soft:'#eff6ff', line:'#bfdbfe', ink:'#172554', muted:'#475569', tableAlt:'#f8fafc', footer:'#1d4ed8'}, boxed: {brand:'#7c2d12', accent:'#f59e0b', soft:'#fffbeb', line:'#fcd34d', ink:'#1f2937', muted:'#6b7280', tableAlt:'#fffbeb', footer:'#7c2d12'}, minimal: {brand:'#111827', accent:'#475569', soft:'#f8fafc', line:'#cbd5e1', ink:'#111827', muted:'#64748b', tableAlt:'#ffffff', footer:'#111827'}, premium: {brand:'#92400e', accent:'#f59e0b', soft:'#fffbeb', line:'#fcd34d', ink:'#1f2937', muted:'#6b7280', tableAlt:'#fff7ed', footer:'#92400e'}, blueclean: {brand:'#075985', accent:'#38bdf8', soft:'#e0f2fe', line:'#bae6fd', ink:'#0f172a', muted:'#475569', tableAlt:'#f0f9ff', footer:'#075985'}, retail: {brand:'#166534', accent:'#22c55e', soft:'#dcfce7', line:'#bbf7d0', ink:'#102a1d', muted:'#4b6353', tableAlt:'#f0fdf4', footer:'#166534'}, service: {brand:'#6d28d9', accent:'#a78bfa', soft:'#f3e8ff', line:'#ddd6fe', ink:'#20113f', muted:'#6b5b84', tableAlt:'#faf5ff', footer:'#6d28d9'}, receipt: {brand:'#334155', accent:'#64748b', soft:'#f8fafc', line:'#cbd5e1', ink:'#111827', muted:'#475569', tableAlt:'#ffffff', footer:'#334155'} }; return palettes[template] || palettes.classic; } function drawText(text, x, y, maxWidth, lineHeight, size, weight, align, color) { ctx.font = (weight || '400') + ' ' + size + 'px Arial'; ctx.textAlign = align || 'left'; ctx.fillStyle = color || '#111827'; var words = String(text || '').split(' '); var line = ''; var lines = []; words.forEach(function (word) { var test = line ? line + ' ' + word : word; if (ctx.measureText(test).width > maxWidth && line) { lines.push(line); line = word; } else { line = test; } }); lines.push(line); lines.forEach(function (lineText, index) { ctx.fillText(lineText, x, y + (index * lineHeight)); }); return y + (lines.length * lineHeight); } function renderCanvas() { var bill = billData(); var colors = palette(bill.template); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, canvas.width, canvas.height); if (state.logoImage) { ctx.drawImage(state.logoImage, 90, 80, 92, 92); } else { ctx.fillStyle = colors.soft; ctx.fillRect(90, 80, 92, 92); ctx.strokeStyle = colors.line; ctx.lineWidth = 2; ctx.strokeRect(90, 80, 92, 92); drawText('V', 136, 142, 92, 40, 52, '800', 'center', colors.brand); } drawText(bill.shopName, 210, 128, 700, 48, 44, '800', 'left', colors.ink); var nextY = drawText(bill.shopAddress, 210, 172, 700, 26, 22, '400', 'left', colors.muted); drawText('Invoice / Bill', 1410, 132, 420, 50, 42, '800', 'right', colors.ink); drawText((bill.shopPhone ? 'Mobile: ' + bill.shopPhone + ' | ' : '') + shop.portal, 210, Math.max(210, nextY + 6), 830, 26, 22, '600', 'left', colors.muted); ctx.fillStyle = '#ffffff'; ctx.fillRect(1020, 240, 390, 90); ctx.strokeStyle = colors.line; ctx.lineWidth = 2; ctx.strokeRect(1020, 240, 390, 90); drawText(bill.billNo, 1048, 280, 330, 30, 28, '800', 'left', colors.brand); drawText('Date: ' + bill.date, 1048, 318, 330, 28, 24, '600', 'left', colors.ink); ctx.strokeStyle = colors.line; ctx.lineWidth = 3; ctx.beginPath(); ctx.moveTo(90, 360); ctx.lineTo(1410, 360); ctx.stroke(); drawText('Bill To', 90, 410, 400, 34, 30, '800', 'left', colors.brand); var custNextY = drawText(bill.customerName, 90, 456, 760, 32, 28, '700', 'left', colors.ink); if (bill.customerAddress) { drawText(bill.customerAddress, 90, custNextY + 6, 760, 26, 22, '400', 'left', colors.muted); } var tableY = 530; ctx.fillStyle = colors.brand; ctx.fillRect(90, tableY, 1320, 62); drawText('Item', 120, tableY + 40, 500, 26, 24, '800', 'left', '#ffffff'); drawText('Qty', 950, tableY + 40, 90, 26, 24, '800', 'right', '#ffffff'); drawText('Rate', 1150, tableY + 40, 150, 26, 24, '800', 'right', '#ffffff'); drawText('Amount', 1380, tableY + 40, 180, 26, 24, '800', 'right', '#ffffff'); var y = tableY + 98; bill.items.forEach(function (item, index) { if (index % 2 === 0) { ctx.fillStyle = colors.tableAlt; ctx.fillRect(90, y - 34, 1320, 58); } drawText(item.name, 120, y, 700, 28, 24, '600', 'left', colors.ink); drawText(item.qty, 950, y, 90, 28, 24, '600', 'right', colors.ink); drawText(money(item.rate), 1150, y, 150, 28, 24, '600', 'right', colors.ink); drawText(money(item.qty * item.rate), 1380, y, 180, 28, 24, '700', 'right', colors.ink); y += 70; }); ctx.strokeStyle = colors.line; ctx.lineWidth = 3; ctx.beginPath(); ctx.moveTo(90, 1450); ctx.lineTo(1410, 1450); ctx.stroke(); drawText('Note', 90, 1510, 400, 34, 28, '800', 'left', colors.brand); drawText(bill.note, 90, 1560, 720, 32, 24, '400', 'left', colors.ink); var totalX = 900; var totalY = 1500; drawText('Subtotal', totalX, totalY, 260, 34, 26, '600', 'left', colors.ink); drawText('Rs. ' + money(bill.subtotal), 1380, totalY, 240, 34, 26, '700', 'right', colors.ink); drawText('Amount', totalX, totalY + 46, 260, 34, 26, '600', 'left', colors.ink); drawText('Rs. ' + money(bill.subtotal), 1380, totalY + 46, 240, 34, 26, '700', 'right', colors.ink); drawText('Discount', totalX, totalY + 92, 260, 34, 26, '600', 'left', colors.ink); drawText('Rs. ' + money(bill.discount), 1380, totalY + 92, 240, 34, 26, '700', 'right', colors.ink); drawText('Tax (' + cleanPercent(bill.taxPercent) + '%)', totalX, totalY + 138, 260, 34, 26, '600', 'left', colors.ink); drawText('Rs. ' + money(bill.taxAmount), 1380, totalY + 138, 240, 34, 26, '700', 'right', colors.ink); ctx.fillStyle = colors.soft; ctx.fillRect(870, totalY + 172, 540, 72); drawText('Grand Total', totalX, totalY + 220, 260, 34, 30, '800', 'left', colors.brand); drawText('Rs. ' + money(bill.total), 1380, totalY + 220, 250, 34, 30, '800', 'right', colors.brand); drawText('Paid', totalX, totalY + 280, 220, 34, 25, '600', 'left', colors.ink); drawText('Rs. ' + money(bill.paid), 1380, totalY + 280, 240, 34, 25, '700', 'right', colors.ink); drawText('Balance', totalX, totalY + 322, 220, 34, 25, '600', 'left', colors.ink); drawText('Rs. ' + money(bill.balance), 1380, totalY + 322, 240, 34, 25, '700', 'right', colors.ink); drawText('Payment Mode', totalX, totalY + 364, 240, 34, 24, '600', 'left', colors.ink); drawText(bill.paymentMode, 1380, totalY + 364, 240, 34, 24, '700', 'right', colors.ink); drawText('Generated by ' + shop.portal, 90, 1990, 700, 30, 22, '400', 'left', colors.muted); drawText('Customer Sign', 1380, 1990, 260, 30, 22, '600', 'right', colors.ink); ctx.strokeStyle = colors.ink; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(1140, 1945); ctx.lineTo(1410, 1945); ctx.stroke(); } function resetBill() { state.selectedId = null; fields.billNo.value = nextBillNo(); fields.billDate.value = today(); fields.customerName.value = 'Walk-in Customer'; fields.customerAddress.value = ''; fields.customerMobile.value = ''; fields.discount.value = 0; fields.taxPercent.value = 0; fields.paidAmount.value = 0; fields.paymentMode.value = 'Cash'; fields.billNote.value = 'Thank you for your business.'; state.items = [{ name: "Online Form Work", qty: 1, rate: 50 }]; renderItems(); renderCanvas(); } Object.keys(fields).forEach(function (key) { if (fields[key] && fields[key].type !== 'file') { fields[key].addEventListener('input', renderCanvas); fields[key].addEventListener('change', renderCanvas); } }); fields.shopLogo.addEventListener('change', function (e) { var file = e.target.files[0]; if (file) { var reader = new FileReader(); reader.onload = function (event) { setLogo(event.target.result); }; reader.readAsDataURL(file); } }); document.querySelectorAll('.bill-mode-btn').forEach(function (button) { button.addEventListener('click', function () { state.printMode = this.dataset.mode; document.querySelectorAll('.bill-mode-btn').forEach(function (b) { b.classList.remove('active'); }); this.classList.add('active'); renderCanvas(); }); }); document.getElementById('addItem').addEventListener('click', function () { addItem('', 1, 0); }); document.querySelectorAll('.bill-quick').forEach(function (button) { button.addEventListener('click', function () { addItem(this.dataset.name, 1, Number(this.dataset.rate)); }); }); function prepareA4PrintSheet(callback) { var printSheet = document.getElementById('billPrintSheet'); if (!printSheet) { if (callback) callback(); return; } var imageData = canvas.toDataURL('image/png'); printSheet.innerHTML = ''; var copy = document.createElement('div'); var image = document.createElement('img'); copy.className = 'bill-print-copy'; image.alt = 'Bill copy'; image.onload = function () { setTimeout(function () { if (callback) callback(); }, 80); }; image.src = imageData; copy.appendChild(image); printSheet.appendChild(copy); } function printWithMode(mode) { var previousMode = state.printMode; state.printMode = mode; renderCanvas(); prepareA4PrintSheet(function () { window.print(); state.printMode = previousMode; renderCanvas(); }); } document.getElementById('printColorBill').addEventListener('click', function () { printWithMode('color'); }); document.getElementById('printBwBill').addEventListener('click', function () { printWithMode('bw'); }); document.getElementById('newBill').addEventListener('click', resetBill); document.getElementById('downloadBill').addEventListener('click', function () { var link = document.createElement('a'); link.href = canvas.toDataURL('image/png'); link.download = (fields.billNo.value || 'invoice') + '.png'; link.click(); }); renderItems(); resetBill(); });

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top