본문으로 바로가기

환경은 Vue.js(Nuxt)이며, 백엔드는 Node.js 입니다.

 

엑셀 다운로드를 구현하기 위해 만들면서 정리하기위해서 작성하였습니다.

엑셀파일(기본 베이스)가 없고, HTML코드도 없는 상태에서 다운로드를 진행하려고 만든 것이기 떄문에

조건이 다르시다면 참고만 하시면 좋을 것 같습니다.

( npm의 xlsx와 sheetJS는 다른거라 생각했는데, npm에서보니 같은 것이여서 신기했습니다. )

 

1. 사용한 첫 번째 방법

<template>
  <div>
    <button
      type="button"
      @click="excelDownload"
    >
      엑셀 다운로드
    </button>
  </div>
</template>

<script>
import XLSX from 'xlsx'

export default {
  methods: {
    excelDownload() {
      const workbook = XLSX.utils.book_new()	// 엑셀 생성
      const firstSheet = XLSX.utils.aoa_to_sheet([
        [
          '이름',	// A1
          '전화번호',	// B1
        ],
        [
          '홍길동',	// A2
          {	// B2
            v: '01012345678',
            z: '@',	// 데이터 포맷 형식 지정
          },
        ],
      ])
      firstSheet['!cols'] = [	// 넓이 지정
        { 'width': 12 },	// A열의 넓이
        { 'width': 17 },	// B열의 넓이
      ]
      
      const secondSheet = XLSX.utils.aoa_to_sheet([
        [
          '테스트입니다.',
        ],
      ])
      
      secondSheet['!rows'] = [	// 높이 지정
        { 'hpx': 100 },	// 1행의 높이
      ]
      
      XLSX.utils.book_append_sheet(workbook, firstSheet, '시트제목1')	// 시트 보내기
      XLSX.utils.book_append_sheet(workbook, secondSheet, '시트제목2')
      XLSX.writeFile(workbook, 'excel_test.xlsx')	// 엑셀 다운로드
    },
  },
}
</script>

 - B2를 입력한 방식처럼 Object 타입으로 입력할 수 있는데(옵션은 맨 마지막에..), 해당 옵션에 s라는 스타일 옵션이 존재는 한다.

    하지만 옵션이 적용이 안된다..

    찾아보니, 커뮤니티버전에서는 스타일이 적용이 안되며, 프로버전을 사용하거나 xlsx-style과 같은 스타일 라이브러리를 추가로 설치해주어야 한다고 한다.

 

시트1 결과
시트2 결과

 

2. 사용한 두 번째 방법

<template>
  <div>
    <button
      type="button"
      @click="excelDownload"
    >
      엑셀 다운로드
    </button>
  </div>
</template>

<script>
import XLSX from 'xlsx'

export default {
  methods: {
    excelDownload() {
      // 기존 테이블이 있다면 생략
      let table1 = document.createElement('table')
      table1.innerHTML = `
        <thead></thead>
        <tbody>
          <tr>
            <th style="background-color: #ffff00; text-align: center;">
              이름
            </th>
            <th style="background-color: #ffff00; text-align: center;">
              전화번호
            </th>
          </tr>
          <tr>
            <td style="text-align: center;">
              홍길동
            </td>
            <td style="text-align: center;">
              01099999999
            </td>
          </tr>
        </tbody>
      `
      let table2 = document.createElement('table')
      table2.innerHTML = `
        <thead></thead>
        <tbody>
          <tr>
            <th style="background-color: #ffff00; text-align: center; font-size"; 30px;>
              안내드립니다.
            </th>
          </tr>
          <tr>
            <td style="text-align: center;">
              네 드렸습니다.
            </td>
          </tr>
        </tbody>
      `

      const wb = XLSX.utils.book_new()
      // 기존 테이블 있다면
      // let fs = XLSX.utils.table_to_sheet(document.getElemenyById('tableId'))
      let fs = XLSX.utils.table_to_sheet(table1)
      fs['B2'].z = '@'
      let ss = XLSX.utils.table_to_sheet(table2)
      ss['!rows'] = [
        { 'hpx': 100 },
      ]
      XLSX.utils.book_append_sheet(wb, fs, '입력란')
      XLSX.utils.book_append_sheet(wb, ss, '공지')
      XLSX.writeFile(wb, 'excel_test2.xlsx')
    },
  },
}
</script>

 - 직접 css를 테이블에 때려박는 하드코딩도 시도해보았다.

 - 스타일이 적용될 것이라 생각하였지만, 결과는 처참히 실패하였다.

 - 또한 포맷형식을 지정해주었음에도 value가 먼저 적용이 된 뒤 포맷이 들어가서 0이 사라진 상태로 출력되었다.

 

결론

 - 내가 테이블 데이터가 있다면 두 번째 방법이 더 편하겠지만, 저처럼 데이터가 없는 빈 상태에서 만들려고 한다면 첫 번째 방법이 더 간편하다.

 

한번에 여러 개의 셀의 포멧을 변경할 때

// 스택오버플로우에서 본 숫자 포멧 적용하는 function
function formatColumn(worksheet, col, fmt) {
  const range = XLSX.utils.decode_range(worksheet['!ref'])
  for (let row = range.s.r + 1; row <= range.e.r; ++row) {
    const ref = XLSX.utils.encode_cell({ r: row, c: col })
    if (worksheet[ref] && worksheet[ref].t === 'n') {
      worksheet[ref].z = fmt
    }
  }
}

 

Merge(셀 병합)

const merge = [
  { s: { r: 1, c: 0 }, e: { r: 1, c: 0 } },	// A2:A3
  { s: { r: 3, c: 0 }, e: { r: 4, c: 0 } },	// A4:A5
]

ws["!merges"] = merge

s: start

e: end

r: row

c: column

A1 = { r: 0, c: 0 }

C7 = { r: 6, c: 2 }

 

셀  오브젝트의 s (Style) 옵션

 - 나중에 style이 추가된 다른 라이브러리를 사용하거나, 프로를 사용할 때를 위한 메모..

let excelCell = {
  v: "VALUE",
  t: "s",
  s: {
    fill: {
      patternType: "none",
      fgColor: {rgb: "FF000000"},
      bgColor: {rgb: "FFFFFFFF"}
    },
    font: {
      name: 'Times New Roman',
      sz: 16,
      color: {rgb: "#FF000000"},
      bold: false,
      italic: false,
      underline: false
    },
    alignment: {
      vertical: "center",
      horizontal: "center",
      indent:0,
      wrapText: true
    },
    border: {
      top: {style: "thin", color: {auto: 1}},
      right: {style: "thin", color: {auto: 1}},
      bottom: {style: "thin", color: {auto: 1}},
      left: {style: "thin", color: {auto: 1}}
    }
  }
}

XLSX.utils 속 method들

생각보다 많은 method들이 존재했지만,

시간이 없어서 아직 사용해보진 못해서 아쉽다..

XLSX.utils의 있는 methods

 

셀 Object 옵션

참고

[ SheetJS github : https://github.com/SheetJS/sheetjs ]

[ SheetJS docs : https://docs.sheetjs.com/ ]

 

반응형