/** * V.AI STUDIO - Excel Export v1102 * FIX: Hình ảnh 100x100px trong Excel */ (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á'); // Column 2 width 15 for 100px image ws.columns = [ {width:6},{width:15},{width:30},{width:15}, {width:22},{width:8},{width:15},{width:15},{width:18},{width:16} ]; // Header title 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; // Table header 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; // Items with 100x100px images 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; // 100px + padding var bgColor = i % 2 === 0 ? 'FFF8FAFC' : 'FFFFFFFF'; row.getCell(1).value = i+1; row.getCell(1).alignment = {horizontal:'center', vertical:'middle'}; // IMAGE 100x100px 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; // Total row 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');