Source

services/export-service.js

import i18n from '@/i18n'
import moment from 'moment'
import { isUnitTest } from '@/utils/unit.js'
const tablesPrefixes = {
  alerts: 'alertes',
  identification: 'identification',
  location: 'localisation',
  locationChrono: 'localisation-chrono',
  locationCrew: 'localisation-equipage',
  locationSensors: 'localisation-capteurs',
  locationMissions: 'localisation-missions',
  locationCircuits: 'localisation-circuits',
  locationHistory: 'localisation-details-historique',
  locationDetailsCircuit: 'localisation-details-circuit',
  locationAlerts: 'localisation-details-alertes',
  locationEvents: 'localisation-details-evenements',
  locationDetailsChrono: 'localisation-details-chrono',
  locationIdentification: 'localisation-details-identification',
}

/**
 * @param {*} code i.g locationDetailsCircuit
 * @returns
 */
function computeFilenameFromTableCode(code = 'table-export') {
  let i18nCode = `export_feature.table_prefixes.${code}`
  if (!i18n.te(i18nCode)) {
    console.warn('i18n expected:', i18nCode)
  }
  let prefix = i18n.te(i18nCode)
    ? i18n.t(i18nCode)
    : tablesPrefixes[code] || code
  return `${prefix}-${moment().format('DDMMYYYY[-]HHmm')}`
}

/**
 *
 * @param {Array} options.data arrayOfObjects
 * @param {String} options.tableCode i.g locationIdentification
 * @param {String} options.format csv/xls (default to csv)
 * @param {Array} options.columns
 * @returns
 */
export function exportDatatable(options = {}) {
  options.format = options.format || 'csv'
  if (options.format === 'xls') {
    return exportToXLS(
      options.data || [],
      computeFilenameFromTableCode(options.tableCode),
      {
        columns: options.columns,
      }
    )
  }
  if (options.format === 'csv') {
    return exportToCSV(
      options.data || [],
      computeFilenameFromTableCode(options.tableCode),
      {
        columns: options.columns,
      }
    )
  }
  throw new Error('INVALID_EXPORT_FORMAT')
}

/**
 * @example
 * exportToXLS([{name:"FOO",size:"200"},{name:"BAR",size:"300"}],"test")
 * exportToXLS([{ name: "FOO", size: "200" },{ name: "BAR", size: "300" }],"test",{columns: {name:"NOMBRE",size:"TAMAÑO"},});
 * exportToXLS([{ name: "FOO", size: "200" },{ name: "BAR", size: "300" }],"test",{columns: ["NAME", "SIZE"]});
 * @param {Array} columns
 * @param {Array} data
 * @param {*} name i.g test
 */
export function exportToXLS(
  arrayOfObjects = [],
  name = 'download',
  options = {}
) {
  let columns = []
  let data = []
  let columnKeys = []
  arrayOfObjects.forEach((item, index) => {
    if (index === 0) {
      columnKeys = Object.keys(item)
      columns =
        options.columns === undefined
          ? Object.keys(item)
          : options.columns instanceof Array
          ? options.columns
          : Object.keys(options.columns).map((key) => options.columns[key])
    }
    data.push(columnKeys.map((key) => item[key]))
  })
  var tableToExcel = (function () {
    const uri = 'data:application/vnd.ms-excel;base64,',
      base64 = function (s) {
        return window.btoa(unescape(encodeURIComponent(s)))
      }
    return function (tableHTML, name = 'Worksheet') {
      let template = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><?xml version="1.0" encoding="UTF-8" standalone="yes"?><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>${name}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--><meta http-equiv="content-type" content="text/plain; charset=UTF-8"/></head><body>${tableHTML}</body></html>`
      var link = document.createElement('a')
      link.download = name.split('.')[0] // + ".xlsx";
      link.href = uri + base64(template)
      link.click()
    }
  })()
  let html = '<tr>' + columns.map((c) => `<th>${c}</th>`).join('') + '</tr>'
  data.forEach((row) => {
    html += `<tr>${row.map((v) => `<td>&#8203;${v}</td>`).join('')}</tr>`
  })
  html = `<table>${html}</table>`
  html = html.split('null').join('')
  tableToExcel(html, name)
}

/**
 * @example
 * exportToCSV([{name:"FOO",size:"200"},{name:"BAR",size:"300"}],"test")
 * exportToCSV([{name:"FOO",size:"200"},{name:"BAR",size:"300"}],"test",{columns:['NAME','SIZE']})
 * @param {*} arrayOfObjects
 * @param {*} filename
 * @returns
 */
export function exportToCSV(
  arrayOfObjects = [],
  filename = 'download',
  options = {}
) {
  let delimiterCharacter = options.delimiterCharacter || ','
  var objectToCSVRow = function (dataObject) {
    var dataArray = new Array()
    for (var o in dataObject) {
      var innerValue = dataObject[o] === null ? '' : dataObject[o].toString()
      var result = innerValue.replace(/"/g, '""')
      result = '"' + result + '"'
      result = result.split('&nbsp;').join(' ')
      dataArray.push(result)
    }
    return dataArray.join(delimiterCharacter) + '\r\n'
  }
  if (!arrayOfObjects.length) {
    return
  }

  let columns =
    options.columns === undefined
      ? Object.keys(arrayOfObjects[0])
      : options.columns instanceof Array
      ? options.columns
      : Object.keys(options.columns).map((key) => options.columns[key])

  var csvContent = 'data:text/csv;charset=utf-8,'
  csvContent += objectToCSVRow(columns)
  arrayOfObjects.forEach(function (item) {
    csvContent += objectToCSVRow(item)
  })
  if (!isUnitTest()) {
    var encodedUri = encodeURI(csvContent)
    var link = document.createElement('a')
    link.setAttribute('href', encodedUri)
    link.setAttribute('download', filename.split('.csv').join('.csv') + '.csv')
    document.body.appendChild(link) // Required for FF
    link.click()
    document.body.removeChild(link)
  }
  return csvContent
}

export default {
  exportToCSV,
  exportToXLS,
  exportDatatable,
}