window.popupCenter = ({ url, title, w, h }) => { // Fixes dual-screen position Most browsers Firefox const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX; const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY; const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width; const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height; const systemZoom = width / window.screen.availWidth; const left = (width - w) / 2 / systemZoom + dualScreenLeft; const top = (height - h) / 2 / systemZoom + dualScreenTop; const newWindow = window.open(url, title, ` scrollbars=yes, width=${w / systemZoom}, height=${h / systemZoom}, top=${top}, left=${left} ` ) if (window.focus) newWindow.focus(); } const ReportArea = _id('cardMenuArea'); const ReportMenu = _id('cardMenuReport'); const SubLap = _id('sublap'); const search = _id('searchInput'); const loaderS = _id('loaderSearch'); let _rightPanelReport = document.querySelector('.content-header-right'); window._filter = function (nx) { let d = el('div'); d.class('modal-filter').css({ position: 'fixed', display: 'flex', alignItems: 'center', justifyContent: 'center', top: '0', left: '0', width: '100vw', height: '100vh', overflow: 'auto', background: 'rgba(125,125,125,0.5)', zIndex: '1524', }) let ct = div().css('background', 'white').radius('8px').width('320px').padding('18px') let dt = _rpt.getData(); if (dt.filter != undefined) { ct.child(div().css('font-size', '18px').text('Filter Laporan')); ct.child(el('hr')); let fill = dt.filter; Object.keys(fill).forEach(function (n) { let ff = fill[n]; if (ff.type == 'number') { let pl = div().css({ marginBottom: '10px', display: 'grid' }); pl.child( el('label').attr('for', ff.name).text(ff.title) ) pl.child( el('input').hold(0).data('type', ff.type).data('kode', n).class('form-control').type('text').id(ff.name).name(ff.name).class('dim') .load(function (c) { ConfStyle(c.el); c.el.inputRupiah() }) ) ct.child(pl) } if (ff.type == 'text') { let pl = div().css({ marginBottom: '10px', display: 'grid' }); pl.child( el('label').attr('for', ff.name).text(ff.title) ) pl.child( el('input').data('type', ff.type).data('kode', n).hold('...').class('form-control').type('text').id(ff.name).name(ff.name).class('dim') ) ct.child(pl) } if (ff.type == 'select') { let pl = div().css({ marginBottom: '10px', display: 'grid' }); pl.child( el('label').attr('for', ff.name).text(ff.title) ); let f = el('select').data('type', ff.type).data('kode', n).class('form-control').id(ff.name).name(ff.name).class('dim') f.child(el('option').val('').html('...')) nx[ff.table].forEach(function (cc) { f.child(el('option').val(cc.id).html(cc.text)) }) pl.child( f ); ct.child(pl) } }) ct.child(el('hr')); ct.child(el('div') .child( el('button').text('simpan').class('btn btn-primary').click(function () { let sx = Array.from(document.querySelectorAll('.dim')).map(function (w) { return { sx: w.dataset.kode, type: w.dataset.type, value: (function () { if (w.dataset.type === 'number') { return 'Rp. ' + w.value.number().currency(0); } else { return w.value; } })(), } }).filter(function (w) { if (w.value != '' && w.value != 'Rp. 0' && w.value != 'Rp. ') { return w; } }) document.querySelector('.modal-filter').remove(); window._dataFilter = sx; localStorage.setItem('report' + location.href, JSON.stringify(sx)) if (window._rpt.dataLoad.filterUnDo != true) { window._rpt.call(); } }) ) .child( el('button').text('clear').css('margin-left', '10px').class('btn btn-warning').click(function () { let sx = []; document.querySelector('.modal-filter').remove(); window._dataFilter = sx; localStorage.setItem('report' + location.href, JSON.stringify(sx)) if (window._rpt.dataLoad.filterUnDo != true) { window._rpt.call(); } }) ) ); } d.child( ct ) d.load(function () { let s = window._rpt.dataLoad.filter; let m = Object.keys(s) .map(function (m) { return s[m]; }) .filter(function (m) { if (m.table != undefined) { return m; } }) .map(function (m) { return { table: m.table, name: m.name, select: m.select } }); m.forEach(function (w) { $(".dim[name='" + w.name + "']").select2(); }) window._dataFilter.forEach(function (w) { if (w.type == 'number') { document.querySelector(".dim[name='" + w.sx + "']").value = w.value.number().currency(0); } else if (w.type == 'select') { $(".dim[name='" + w.sx + "']").val(w.value).trigger('change'); } else { document.querySelector(".dim[name='" + w.sx + "']").value = w.value; } }) }) document.body.appendChild(d.get()); } if (_rightPanelReport != undefined) { _rightPanelReport.appendChild( div().html(`
`).load(function () { $("#reportrange").click(function () { setTimeout(function () { document.querySelector(".ranges .active").scrollIntoView() }, 10) }) $(function () { window._cekSession = (function () { return { get: function () { let t = localStorage.getItem(location.href + 'ds'); let w = localStorage.getItem(location.href + 'dn'); if (t != undefined) { return { start: t, end: w } } return null; }, set: function (start, end) { localStorage.setItem(location.href + 'ds', start) localStorage.setItem(location.href + 'dn', end) } } })() window._startDate = moment().startOf('month'); window._endDate = moment().endOf('month'); if (window._cekSession.get() != null) { window._startDate = moment(window._cekSession.get().start) window._endDate = moment(window._cekSession.get().end); } function cb(d1, d2) { $('#reportrange span').html(d1.format('MMMM D, YYYY') + ' - ' + d2.format('MMMM D, YYYY')); window._rpt.call() } function cb2(d1, d2) { window._startDate = d1 window._endDate = d2 window._cekSession.set(d1, d2) $('#reportrange span').html(d1.format('MMMM D, YYYY') + ' - ' + d2.format('MMMM D, YYYY')); window._rpt.call() } $('#reportrange').daterangepicker({ startDate: _startDate, endDate: _endDate, ranges: { 'Januari': [moment(moment().format('YYYY') + '-01').startOf('month'), moment(moment().format('YYYY') + '-01').endOf('month')], 'Februari': [moment(moment().format('YYYY') + '-02').startOf('month'), moment(moment().format('YYYY') + '-02').endOf('month')], 'Maret': [moment(moment().format('YYYY') + '-03').startOf('month'), moment(moment().format('YYYY') + '-03').endOf('month')], 'April': [moment(moment().format('YYYY') + '-04').startOf('month'), moment(moment().format('YYYY') + '-04').endOf('month')], 'Mei': [moment(moment().format('YYYY') + '-05').startOf('month'), moment(moment().format('YYYY') + '-05').endOf('month')], 'Juni': [moment(moment().format('YYYY') + '-06').startOf('month'), moment(moment().format('YYYY') + '-06').endOf('month')], 'Juli': [moment(moment().format('YYYY') + '-07').startOf('month'), moment(moment().format('YYYY') + '-07').endOf('month')], 'Agustus': [moment(moment().format('YYYY') + '-08').startOf('month'), moment(moment().format('YYYY') + '-08').endOf('month')], 'September': [moment(moment().format('YYYY') + '-09').startOf('month'), moment(moment().format('YYYY') + '-09').endOf('month')], 'Oktober': [moment(moment().format('YYYY') + '-10').startOf('month'), moment(moment().format('YYYY') + '-10').endOf('month')], 'November': [moment(moment().format('YYYY') + '-11').startOf('month'), moment(moment().format('YYYY') + '-11').endOf('month')], 'Desember': [moment(moment().format('YYYY') + '-12').startOf('month'), moment(moment().format('YYYY') + '-12').endOf('month')], '1 Tahun': [moment().startOf('year'), moment().endOf('year')] } }, cb2); cb(_startDate, _endDate); }); }).get() ) } // search action search.addEventListener('keydown', function () { loaderS.style.display = 'block'; }, false); search.addEventListener('search', function () { loaderS.style.display = 'block'; Report(globalThis.reportActive).unload().call(); }, false); search.addEventListener('keyup', delay(function () { Report(globalThis.reportActive).unload().call(); }, 500), false); // end search action const printAction = document.querySelector('.print-data'); const filterAction = document.querySelector('.filter-data'); filterAction.style.display = 'none'; let dataPrintX = {}; window._dataFilter = []; if (localStorage.getItem('report' + location.href) != undefined) { window._dataFilter = JSON.parse(localStorage.getItem('report' + location.href)); } // Add event listener for export if (printAction) { printAction.addEventListener('click', function(e) { e.preventDefault(); exportToExcelWithStyle(); }); } // filter click filterAction.addEventListener('click', function () { if (window._rpt.dataLoad.filter != undefined) { let s = window._rpt.dataLoad.filter; let m = Object.keys(s) .map(function (m) { return s[m]; }) .filter(function (m) { if (m.table != undefined) { return m; } }) .map(function (m) { return { table: m.table, select: m.select } }); let _ld = cssLoader() $.ajax({ url: dataApi.path + 'admin/master/api/data', dataType: 'json', method: 'POST', data: { data: m }, success: function (res) { _ld.remove(); window._filter(res); }, error: function () { _ld.remove(); Swal('Warning', 'your connection is lost', 'warning'); throw 'error connection'; } }) } else { window._filter(); } }); // Backup fungsi export yang lama const exportToExcelBasic = function() { let reportExcelmain = document.getElementById('tableReport'); let reportExcel = el('table').html(reportExcelmain.innerHTML).get(); console.log(reportExcel) /* Create worksheet from HTML DOM TABLE */ for (let tdR of Array.from(reportExcel.querySelectorAll('td'))) { if (tdR.getAttribute('style').indexOf('mso-number-format') != -1 && tdR.innerHTML.indexOf('Rp') != -1) { // Convert currency to number but keep the format let value = tdR.innerText.replace('Rp', '').replace(/\./g, '').trim(); tdR.innerText = value; // Set Excel format to Indonesian currency format with Rp prefix and proper thousand separators tdR.setAttribute('style', 'mso-number-format:"Rp "#,##0'); } if (tdR.dataset.type && tdR.dataset.type === 'date') { // Parse date from dd-mm-yyyy format const dateText = tdR.innerText.trim(); if (dateText) { const [day, month, year] = dateText.split('-').map(num => parseInt(num)); if (!isNaN(day) && !isNaN(month) && !isNaN(year)) { // Array nama bulan dalam Bahasa Indonesia const monthNames = [ 'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember' ]; // Format dengan leading zero untuk tanggal const formattedDay = day.toString().padStart(2, '0'); tdR.innerText = `${formattedDay} ${monthNames[month - 1]} ${year}`; // Set Excel format untuk memastikan format tetap sama tdR.setAttribute('style', tdR.getAttribute('style') + ';mso-number-format:"dd mmmm yyyy"'); } } } } const wb = XLSX.utils.table_to_book(reportExcel, { sheet: 'sheet-1' }); /* Export to file (start a download) */ const ws = wb.Sheets['sheet-1']; // Get the worksheet /* Calculate and set column widths */ const range = XLSX.utils.decode_range(ws['!ref']); const colWidths = []; for (let C = range.s.c; C <= range.e.c; ++C) { let maxWidth = 10; // Default width for (let R = range.s.r; R <= range.e.r; ++R) { const cell_address = XLSX.utils.encode_cell({ r: R, c: C }); const cell = ws[cell_address]; if (cell && cell.v) { const cellValue = cell.v.toString(); maxWidth = Math.max(maxWidth, cellValue.length + 2); } } colWidths.push({ wch: maxWidth }); } ws['!cols'] = colWidths; /* Export to file (start a download) */ XLSX.writeFile(wb, 'Laporan.xlsx'); } // Fungsi export baru yang mempertahankan style HTML const exportToExcelWithStyle_bc = function() { let reportExcelmain = document.getElementById('tableReport'); let reportExcel = el('table').html(reportExcelmain.innerHTML).get(); // Clone table untuk mempertahankan style const tableClone = reportExcel.cloneNode(true); // Proses data dan format for (let tdR of Array.from(tableClone.querySelectorAll('td'))) { if (tdR.getAttribute('style')?.indexOf('mso-number-format') != -1 && tdR.innerHTML.indexOf('Rp') != -1) { // Convert currency to number let value = tdR.innerText.replace('Rp', '').replace(/\./g, '').replace(/,/g, '').trim(); tdR.innerText = new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(value); tdR.dataset.t = 'n'; tdR.dataset.z = '"Rp"#,##0.00'; tdR.style.textAlign = 'right'; } if (tdR.dataset.type && tdR.dataset.type === 'date') { // Parse date from dd-mm-yyyy format const dateText = tdR.innerText.trim(); if (dateText) { const [day, month, year] = dateText.split('-').map(num => parseInt(num)); if (!isNaN(day) && !isNaN(month) && !isNaN(year)) { // Array nama bulan dalam Bahasa Indonesia const monthNames = [ 'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember' ]; // Format dengan leading zero untuk tanggal const formattedDay = day.toString().padStart(2, '0'); tdR.innerText = `${formattedDay} ${monthNames[month - 1]} ${year}`; // Set cell type dan format untuk tanggal tdR.dataset.t = 'd'; // date type tdR.dataset.z = 'dd mmmm yyyy'; // format string } } } // Rata kanan untuk semua cell yang berisi angka if (tdR.dataset.type === 'number' || !isNaN(tdR.innerText.replace(/[,.]/g, ''))) { tdR.style.textAlign = 'right'; } } // Konversi ke Excel dengan mempertahankan style const wb = XLSX.utils.table_to_book(tableClone, { sheet: 'sheet-1', raw: true, cellStyles: true, cellDates: true, dateNF: 'dd mmmm yyyy', cellNF: true }); const ws = wb.Sheets['sheet-1']; // Set column widths const range = XLSX.utils.decode_range(ws['!ref']); const colWidths = []; for (let C = range.s.c; C <= range.e.c; ++C) { let maxWidth = 10; for (let R = range.s.r; R <= range.e.r; ++R) { const cell_address = XLSX.utils.encode_cell({ r: R, c: C }); const cell = ws[cell_address]; if (cell && cell.v) { const cellValue = cell.v.toString(); maxWidth = Math.max(maxWidth, cellValue.length + 2); // Apply number format to currency cells if (cell.t === 'n' && tableClone.rows[R].cells[C].dataset.type === 'number') { cell.z = '#,##0.00'; cell.w = XLSX.SSF.format('#,##0.00', cell.v); } } } colWidths.push({ wch: maxWidth }); } ws['!cols'] = colWidths; // Export ke file XLSX.writeFile(wb, 'Laporan_Styled.xlsx'); }; const exportToExcelWithStyle = function() { let reportExcelmain = document.getElementById('tableReport'); if (!reportExcelmain) { Swal('Error', 'Table not found', 'error'); return; } let reportExcel = el('table').html(reportExcelmain.innerHTML).get(); // Clone table untuk mempertahankan style const tableClone = reportExcel.cloneNode(true); let excelData = { data: [], columnTypes: [] }; // Get headers const headers = Array.from(tableClone.querySelectorAll('th')).map(th => th.innerText); excelData.headers = headers; // Process rows const rows = Array.from(tableClone.querySelectorAll('tr')).slice(1); rows.forEach(row => { let rowData = {}; Array.from(row.querySelectorAll('td')).forEach((td, index) => { let value = td.innerText.trim(); let type = 'general'; if (td.getAttribute('style')?.indexOf('mso-number-format') != -1 && value.indexOf('Rp') != -1) { // Currency type value = value.replace('Rp', '').replace(/\./g, '').replace(/,/g, '').trim(); value = parseFloat(value); type = 'currency'; } else if (td.dataset.type === 'date') { // Date type - Convert from dd-mm-yyyy to yyyy-mm-dd const [day, month, year] = value.split('-').map(num => parseInt(num)); if (!isNaN(day) && !isNaN(month) && !isNaN(year)) { // Create date in yyyy-mm-dd format value = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`; type = 'date'; } } else if (td.dataset.type === 'number' || !isNaN(value.replace(/[,.]/g, ''))) { // Number type value = parseFloat(value.replace(/[,.]/g, '')); type = 'number'; } rowData[headers[index]] = { value: value, type: type }; }); excelData.data.push(rowData); }); // Get column types headers.forEach((header, index) => { let type = 'general'; if (excelData.data.some(row => row[header].type === 'currency')) { type = 'currency'; } else if (excelData.data.some(row => row[header].type === 'date')) { type = 'date'; } else if (excelData.data.some(row => row[header].type === 'number')) { type = 'number'; } excelData.columnTypes.push({ header: header, type: type }); }); // Debug: Log data being sent console.log('Data being sent to export:', excelData); // Create form and submit const form = document.createElement('form'); form.method = 'POST'; form.action = '/usp/export/excel/auto'; form.target = '_blank'; // Open in new tab/window form.enctype = 'application/x-www-form-urlencoded'; // Add data as hidden input const dataInput = document.createElement('input'); dataInput.type = 'hidden'; dataInput.name = 'data'; dataInput.value = JSON.stringify(excelData); form.appendChild(dataInput); // Debug: Log form data console.log('Form data:', { method: form.method, action: form.action, data: dataInput.value }); // Add form to document, submit, and remove document.body.appendChild(form); form.submit(); document.body.removeChild(form); }; const Report = function (a = 'instansi') { let conf = { kode: a, idReport: false, contentHead: false, contentArea: false, dataLoad: {}, loadContentReport: function () { this.idReport = Date.now(); this.contentHead = ReportArea.querySelector('table thead'); this.contentArea = ReportArea.querySelector('table tbody'); return this; } , close: function () { history.pushState({}, "", '{{PATH}}/admin/laporan'); ReportArea.style.display = 'none'; ReportMenu.style.display = 'block'; } , loadTableData(data) { let ct = this.dataLoad; let co = this.contentArea; co.innerHTML = ''; let hM = '