Nuxt3 and PrimeVue DataTable - Exporting to XLSX Format with Image In Cells

50 Views Asked by At

I'm using PrimeVue's DataTable component in a Nuxt 3 project, and I'm trying to export the table data to an XLSX file. The primary reason for choosing this file format is to be able to include images in the cells.

import * as XLSX from 'xlsx';
function exportCSVHandler() {

  const data = props.data;

  const fields = selectedColumns.value.map((col) => col.field);


  const filteredData = data.map((item) => {
    const filteredItem = {};
    fields.forEach((field) => {
      filteredItem[field] = item[field];
    });
    return filteredItem;
  });


  
  if (dataTableRef.value) {
    const ws = XLSX.utils.json_to_sheet(filteredData);


    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'Sheet 1');

    
    const fileName = 'exported_data.xlsx';
    XLSX.writeFile(wb, fileName);
   
  }
}

Here is the data table

<Button label="download" @click="exportCSVHandler" />
<DataTable
    ref="dataTableRef"
    v-model:filters="filters"
    :value="filteredData"
    show-gridlines
    paginator
    responsive-layout="scroll"
    :rows="5"
    :row-hover="true"
    data-key="id"
    filter-display="menu"
    overlay-visible
    striped-rows
    csv-separator
    :global-filter-fields="['filled_on', 'text_filled']"
    paginator-template="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
    current-page-report-template="Showing {first} to {last} of {totalRecords} entries"
    @update:filters="onFilterChange">
  <template #header>
   
    <DataTableFilters
      :filters="filters"
      :hasFilterActions="props.hasFilterActions"
      :typefilter="typefilter"
      @filterData="filterData"
      @clearFilter="clearFilter"
    />

    <div class="text-left mt-7 w-3/4 sm:w-full text-sm">
      <MultiSelect
        v-model="selectedColumns"
        :options="columns"
        optionLabel="header"
        display="chip"
        placeholder="Select Columns"
      />
    </div>

  </template>
  <template #empty>
    Select a template to display data.
  </template>
  <template #loading>
    Loading data. Please wait.
  </template>
  <Column
    v-for="(column, index) of selectedColumns"
    :field="column.field"
    :header="column.header"
    :key="column.field + '_' + index"
    :data-type="column.data_type"
    :style="column.style"
    :filter-field="column.filterField"
    :show-filter-match-modes="column.showFilterMatchModes"
    :filter-menu-style="{ width: '14rem' }"
  >
  <template #body="{ data }">
    <div v-if="column.header === 'Image'">
     
      <div class=" flex justify-content-center">
          <Button icon="pi pi-eye" outlined text  @click="toggleDialog(index, data[column.field])"/>       
      </div>
    </div>
    <div v-else-if="column.header === 'Filled On'">
      <i class="pi pi-calendar text-primaryBlue font-bold mr-4 text-xl"></i>
      {{ formatDate(data[column.field]) }}
    </div>
    <div v-else class="flex ">
      
      {{ data[column.field] }}
    </div>
  </template>
    
  <template v-if="column.data_type === 'date'" #filter="{ filterModel }">
    <Calendar
      v-model="filterModel.value"
      date-format="mm/dd/yy"
      placeholder="mm/dd/yyyy"
      mask="99/99/9999"
    />
  </template>
    
  <template v-else-if="column.header !== 'Image'" #filter="{ filterModel }">
    <InputText
      v-model="filterModel.value"
      type="text"
      class="p-column-filter"
      :placeholder="getPlaceholder(column.header)"
    />
  </template>
</Column>
</DataTable>

Here is the data format

const data = [
{
    id: 6,
    filled_on: new Date('2024-04-22'),
    image: 'https://assets-global.website-files.com/5ebb0930dd82631397ddca92/61b8ef1f82c1b3167fe39e0a_product-template-forms-finance.png',
    text_filled: 'Sed Do Eiusmod',
    type: 'Paper',
    templateName: 'Temp1',
  },
]

I tried different libraries and converting image links to base64(ERROR: text length must not exceed 32767 characters), I haven't been successful.

0

There are 0 best solutions below