아래와 같이 지정된 양식의 출력을 원한다면 ExcelJS 컴포넌트를 적용할수 있습니다.
해당 기능을 적용하려면 폼의 스크립트로 함수를 생성하고 
버턴을 추가해서 해당 스크립트에서 지정한 함수를 호출하면 됩니다

GitHub - exceljs/exceljs: Excel Workbook Manager

Excel Workbook Manager. Contribute to exceljs/exceljs development by creating an account on GitHub.

https://www.github.com/exceljs/exceljs?tab=readme-ov-file





form.excel_export=()=>{
  // 리포트제목
  let reportName = "요청사항목록";
  // 리포트제목
  var headers = ["요청사항번호", "접수일", "상태", "요청사항"];
  // 셀간격
  let cellWidth= [20,15,10,60];
  // 출력할 자료 포멧변경 (특히 날짜)
  var data = form.dataGrid.rows.map(row=> {
      return [
        row["요청사항번호"],
        new Date(row["접수일"]).$toFormat('yyyy-MM-dd'),
        row["상태"],
        row["요청사항이름"]
      ];
  })

  // ** 특별한 경우를 제외하면 복사 붙여넣기 후에 손대지 마시요 */

  Jinja.require.load("ExcelJS").then(() => {
    var exportRows = [headers, ...data];
    var borderStyle = {
      top: { style: 'thin', color: { argb: 'FF000000' } },
      left: { style: 'thin', color: { argb: 'FF000000' } },
      bottom: { style: 'thin', color: { argb: 'FF000000' } },
      right: { style: 'thin', color: { argb: 'FF000000' } }
    };
    var workbook = new ExcelJS.Workbook();
    var worksheet = workbook.addWorksheet('My Sheet');
    worksheet.getColumn('A').width = 1; // 원하는 너비로 설정
    worksheet.getRow(1).height = 5; // 원하는 높이로 설정
    let mgCel = "B2:"+String.fromCharCode(65+headers.length-2)+"3";
    worksheet.mergeCells(mgCel); // 셀 병합
    worksheet.getCell('B2').value = reportName
    worksheet.getCell('B2').alignment = { vertical: 'middle', horizontal: 'center' };
    worksheet.getCell('B2').border = borderStyle
    worksheet.getCell('B2').font = {
      size: 18, // 폰트 크기 설정
      bold: true // 굵게 설정
    };
    let d11Cell = String.fromCharCode(65+headers.length-1)+"2";
    let d12Cell = String.fromCharCode(65+headers.length)+"2";
    let d21Cell = String.fromCharCode(65+headers.length-1)+"3";
    let d22Cell = String.fromCharCode(65+headers.length)+"3";
    worksheet.getCell(d11Cell).value = '작성일자';
    worksheet.getCell(d11Cell).border = borderStyle;
    worksheet.getCell(d11Cell).alignment = { vertical: 'middle', horizontal: 'center' };
    worksheet.getCell(d12Cell).value = new Date();
    worksheet.getCell(d12Cell).border = borderStyle;
    worksheet.getCell(d12Cell).alignment = { vertical: 'middle', horizontal: 'center' };
    worksheet.getCell(d21Cell).value = '작성자';
    worksheet.getCell(d21Cell).border = borderStyle;
    worksheet.getCell(d21Cell).alignment = { vertical: 'middle', horizontal: 'center' };
    worksheet.getCell(d22Cell).value = Jinja.uo.USER_NAME;
    worksheet.getCell(d22Cell).border = borderStyle;
    worksheet.getCell(d22Cell).alignment = { vertical: 'middle', horizontal: 'center' };
    // 간격설정
    cellWidth.forEach( (width, index)=>{
      worksheet.getColumn(String.fromCharCode(66+index)).width = width;
    })
    exportRows.forEach((row, index) => {
      var startRow = 4; // B4부터 시작
      row.forEach((cellValue, colIndex) => {
        var cell = worksheet.getCell(startRow + index, 2 + colIndex); // B열은 2번째 열
        cell.value = cellValue;
        cell.alignment = { vertical: 'middle', horizontal: 'center' };
        cell.border = borderStyle
        // 첫 번째 행만 배경색 설정
        if (index === 0) {
          cell.fill = {
            type: 'pattern',
            pattern: 'solid',
            fgColor: { argb: 'FFD3D3D3' } // 연한 회색
          };
        }
      });
    });
    workbook.xlsx.writeBuffer().then((buffer) => {
      // Blob 생성
      const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
      // 링크 생성 및 클릭하여 다운로드
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = reportName+'.xlsx';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    });
  }).catch((error) => {
    console.error("라이브러리 로드에 실패했습니다: ", error);
  });

}