| |
| |
| |
| |
| (function(){ |
| 'use strict'; |
|
|
| function fmt(n){ |
| if(n==null||n==='')return'0đ'; |
| var num=typeof n==='string'?parseFloat(n.replace(/[^\d.-]/g,'')):Number(n); |
| if(isNaN(num))return'0đ'; |
| return num.toLocaleString('vi-VN')+'đ'; |
| } |
|
|
| async function fetchImageArrayBuffer(url){ |
| if(!url||!url.startsWith('http')) return null; |
| try{ |
| var r = await fetch(url,{mode:'cors'}); |
| if(r.ok) return await r.arrayBuffer(); |
| }catch(e){} |
| try{ |
| var r2 = await fetch('https://api.allorigins.win/raw?url=' + encodeURIComponent(url)); |
| if(r2.ok) return await r2.arrayBuffer(); |
| }catch(e){} |
| return null; |
| } |
|
|
| function getOrderCode(){ |
| var n = document.getElementById('quoteName')?.value || ''; |
| var h = window.location.hash; |
| var today = new Date(), dd=today.getDate().toString().padStart(2,'0'), mm=(today.getMonth()+1).toString().padStart(2,'0'), yy=today.getFullYear().toString().slice(-2); |
| var ini=''; |
| if(n && n.trim()){ |
| n.trim().split(/\s+/).forEach(function(w){ |
| if(w && /[A-Z]/.test(w.charAt(0).toUpperCase())) ini += w.charAt(0).toUpperCase(); |
| }); |
| } |
| return 'VAS'+(ini||'X')+dd+mm+yy; |
| } |
|
|
| window.exportExcel = async function(){ |
| var cart = window.cart || []; |
| if(!cart.length){alert('Giỏ trống!');return;} |
| |
| if(typeof ExcelJS === 'undefined'){ |
| var s = document.createElement('script'); |
| s.src = 'https://cdn.jsdelivr.net/npm/exceljs@4.4.0/dist/exceljs.min.js'; |
| document.head.appendChild(s); |
| await new Promise(function(r){s.onload=r}); |
| } |
| |
| try{ |
| var code = getOrderCode(); |
| var wb = new ExcelJS.Workbook(), ws = wb.addWorksheet('Báo giá'); |
| |
| |
| ws.columns = [ |
| {width:6},{width:15},{width:30},{width:15}, |
| {width:22},{width:8},{width:15},{width:15},{width:18},{width:16} |
| ]; |
| |
| |
| ws.mergeCells('A1:J1'); |
| ws.getCell('A1').value = 'BẢNG BÁO GIÁ'; |
| ws.getCell('A1').font = {bold:true, size:18, color:{argb:'FFDB9815'}}; |
| ws.getCell('A1').alignment = {horizontal:'center'}; |
| ws.getRow(1).height = 30; |
| |
| |
| var hr = ws.getRow(3); |
| ['STT','Hình','Tên sản phẩm','Mã SP','Thông tin','SL','Đơn giá','Giá CK','Thành tiền','Ghi chú'].forEach(function(h,i){ |
| var c = hr.getCell(i+1); |
| c.value = h; |
| c.font = {bold:true, color:{argb:'FFFFFFFF'}, size:9}; |
| c.fill = {type:'pattern', pattern:'solid', fgColor:{argb:'FF003F62'}}; |
| c.alignment = {horizontal:'center', vertical:'middle'}; |
| }); |
| hr.height = 20; |
| |
| |
| var firstRow = 5; |
| await Promise.all(cart.map(async function(c, i){ |
| var p = window.D && D[c.idx] ? D[c.idx] : null; |
| var row = ws.getRow(firstRow + i); |
| row.height = 120; |
| |
| var bgColor = i % 2 === 0 ? 'FFF8FAFC' : 'FFFFFFFF'; |
| |
| row.getCell(1).value = i+1; |
| row.getCell(1).alignment = {horizontal:'center', vertical:'middle'}; |
| |
| |
| if((p && p.image) || c.image){ |
| var imgUrl = p?.image || c.image; |
| var imgBuf = await fetchImageArrayBuffer(imgUrl); |
| if(imgBuf){ |
| try{ |
| wb.addImage(wb.addImage({buffer:imgBuf, extension:'png'}), |
| {tl:{col:1, row:firstRow+i-1}, ext:{width:100, height:100}}); |
| }catch(e){} |
| } |
| } |
| |
| row.getCell(3).value = c.name || (p?p.name||p.n:'') || ''; |
| row.getCell(3).font = {bold:true, size:9}; |
| row.getCell(4).value = c.sku || (p?p.sku||p.model:'') || ''; |
| row.getCell(6).value = Number(c.qty||1); |
| row.getCell(7).value = Number(c.priceNum||(p?p.priceNum:0)||0); |
| row.getCell(7).numFmt = '#,##0"đ"'; |
| row.getCell(8).value = Number(c.priceNum||(p?p.priceNum:0)||0); |
| row.getCell(8).numFmt = '#,##0"đ"'; |
| row.getCell(9).value = Number(c.priceNum||(p?p.priceNum:0)||0) * Number(c.qty||1); |
| row.getCell(9).numFmt = '#,##0"đ"'; |
| |
| for(var ci=1; ci<=10; ci++){ |
| row.getCell(ci).fill = {type:'pattern', pattern:'solid', fgColor:{argb:bgColor}}; |
| } |
| })); |
| |
| var lastRow = firstRow + cart.length - 1; |
| |
| ws.getCell('A'+(lastRow+2)).value = 'TỔNG CỘNG'; |
| ws.getCell('A'+(lastRow+2)).font = {bold:true, size:13, color:{argb:'FFFFFFFF'}}; |
| ws.getCell('A'+(lastRow+2)).fill = {type:'pattern', pattern:'solid', fgColor:{argb:'FF003F62'}}; |
| ws.getCell('I'+(lastRow+2)).value = {formula:'SUM(I'+firstRow+':I'+lastRow+')'}; |
| ws.getCell('I'+(lastRow+2)).numFmt = '#,##0"đ"'; |
| ws.getCell('I'+(lastRow+2)).font = {bold:true, size:14, color:{argb:'FFF0B840'}}; |
| |
| wb.calcProperties.fullCalcOnLoad = true; |
| var buf = await wb.xlsx.writeBuffer(); |
| var blob = new Blob([buf], {type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}); |
| var url = URL.createObjectURL(blob); |
| var a = document.createElement('a'); |
| a.href = url; |
| a.download = code + '.xlsx'; |
| document.body.appendChild(a); |
| a.click(); |
| setTimeout(function(){ document.body.removeChild(a); URL.revokeObjectURL(url); }, 30000); |
| |
| console.log('[VAI] Excel export OK - hình ảnh 100px'); |
| if(typeof showToast === 'function') showToast('✅ Excel OK - Hình ảnh 100px'); |
| |
| }catch(e){ |
| console.error('[VAI] Excel error:', e); |
| alert('Lỗi: '+e.message); |
| } |
| }; |
|
|
| console.log('[VAI v1102] Excel fix loaded - 100px images ready'); |