Quasar导出表格过滤/排序后的数据到csv

642 阅读2分钟

前言

Quasar官方文档中有导出表格数据到csv的案例,但如果表格中有过滤/排序,导出后的数据还是原数据,对于如何解决这个问题,仅有一行提示。

image.png

官方导出数据案例

<div class="w-full h-full">
    <div class="q-pa-md">
        <q-table
            title="Treats"
            :rows="rows"
            :columns="columns"
            color="primary"
            row-key="name"
        >
            <template v-slot:top-right>
                <q-btn
                    color="primary"
                    icon-right="archive"
                    label="Export to csv"
                    no-caps
                    @click="exportTable"
                />
            </template>
        </q-table>
    </div>
</div>
import { exportFile } from 'quasar'

export default {
  data () {
    return {
      columns: [
        {
          name: 'desc',
          required: true,
          label: 'Dessert (100g serving)',
          align: 'left',
          field (row) { return row.name },
          sortable: true,
        },
        {
          name: 'calories',
          align: 'center',
          label: 'Calories',
          field: 'calories',
          sortable: true,
        },
        {
          name: 'fat',
          label: 'Fat (g)',
          field: 'fat'
        },
        {
          name: 'carbs',
          label: 'Carbs (g)',
          field: 'carbs' 
        },
        {
          name: 'protein',
          label: 'Protein (g)',
          field: 'protein'
        },
        {
          name: 'calcium',
          label: 'Calcium (%)',
          field: 'calcium'
        },
        {
          name: 'sodium',
          label: 'Sodium (mg)',
          field: 'sodium'
        },
        {
          name: 'iron',
          label: 'Iron (%)',
          field: 'iron'
        },
      ],

      rows: [
        {
          name: 'Frozen Yogurt',
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0,
          sodium: 87,
          calcium: '14%',
          iron: '1%',
        },
        {
          name: 'Ice cream sandwich',
          calories: 237,
          fat: 9.0,
          carbs: 37,
          protein: 4.3,
          sodium: 129,
          calcium: '8%',
          iron: '1%',
        },
        {
          name: 'Eclair',
          calories: 262,
          fat: 16.0,
          carbs: 23,
          protein: 6.0,
          sodium: 337,
          calcium: '6%',
          iron: '7%',
        },
        {
          name: 'Cupcake',
          calories: 305,
          fat: 3.7,
          carbs: 67,
          protein: 4.3,
          sodium: 413,
          calcium: '3%',
          iron: '8%',
        },
        {
          name: 'Gingerbread',
          calories: 356,
          fat: 16.0,
          carbs: 49,
          protein: 3.9,
          sodium: 327,
          calcium: '7%',
          iron: '16%',
        },
        {
          name: 'Jelly bean',
          calories: 375,
          fat: 0.0,
          carbs: 94,
          protein: 0.0,
          sodium: 50,
          calcium: '0%',
          iron: '0%',
        },
        {
          name: 'Lollipop',
          calories: 392,
          fat: 0.2,
          carbs: 98,
          protein: 0,
          sodium: 38,
          calcium: '0%',
          iron: '2%',
        },
        {
          name: 'Honeycomb',
          calories: 408,
          fat: 3.2,
          carbs: 87,
          protein: 6.5,
          sodium: 562,
          calcium: '0%',
          iron: '45%',
        },
        {
          name: 'Donut',
          calories: 452,
          fat: 25.0,
          carbs: 51,
          protein: 4.9,
          sodium: 326,
          calcium: '2%',
          iron: '22%',
        },
        {
          name: 'KitKat',
          calories: 518,
          fat: 26.0,
          carbs: 65,
          protein: 7,
          sodium: 54,
          calcium: '12%',
          iron: '6%',
        },
      ],
    }
  },

  methods: {
    wrapCsvValue (val, formatFn) {
      let formatted = formatFn !== void 0
      ? formatFn(val)
      : val

      formatted = formatted === void 0 || formatted === null
        ? ''
      : String(formatted)

      formatted = formatted.split('"').join('""')
      /**
             * Excel accepts \n and \r in strings, but some other CSV parsers do not
             * Uncomment the next two lines to escape new lines
             */
      // .split('\n').join('\n')
      // .split('\r').join('\r')

      return `"${ formatted }"`
    },

    exportTable () {
      // naive encoding to csv format
      const {
        columns,
        rows,
        wrapCsvValue,
      } = this
      const content = [columns.map((col) => { return wrapCsvValue(col.label) })].concat(
        rows.map((row) => {
          return columns.map((col) => {
            return wrapCsvValue(
              typeof col.field === 'function'
              ? col.field(row)
              : row[col.field === void 0 ? col.name : col.field],
              col.format
            )
          }).join(',')
        })
      ).join('\r\n')

      const status = exportFile(
        'table-export.csv',
        content,
        'text/csv'
      )

      if (status !== true) {
        this.$q.notify({
          message: 'Browser denied file download...',
          color: 'negative',
          icon: 'warning',
        })
      }
    },
  },
}

image.png

点击Export to csv,会自动下载csv文件,打开可以看到数据导出成功。

image.png

之后我们将Calories降序排序再导出

image.png

可以看到导出后的数据是原数据,并不是降序后的数据

image.png

导出过滤/排序后的数据

我们给q-table打个ref,可以找到在this.$refs.table上找到filteredSortedRows

<q-table
    ref="table"
    title="Treats"
    :rows="rows"
    :columns="columns"
    color="primary"
    row-key="name"
  >
    // ...
  </q-table>

可以看到filteredSortedRows的初始值就是原数据

image.png

当我们点击排序按钮后,点击Export to csv时再输出一次filteredSortedRows,可以看到filteredSortedRow变成了排序后的数据,而原数据rows在排序后并没有改变,很明显filteredSortedRows是原数据rows的浅拷贝。

image.png

因此如果我们想导出过滤/排序后的数据,只需要将从rows上拿原数据改为从filteredSortedRows中拿修改后的数据即可。

// const { columns, rows, wrapCsvValue } = this
const { columns, $refs: { table: { filteredSortedRows: rows } }, wrapCsvValue } = this
// ...

可以看到,成功导出排序后的数据

image.png