【utils】前端导出数据:csv与txt【2023-02-21】

介绍

目前代码支持两种导出方式:

  • csvExport:导出为csv格式
  • plainExport:纯文本形式导出,默认后缀为txt

模块要求:

  • antd

csvExport

import { message } from 'antd';

const csvExport = (data, fileName='export.csv', removeColName = false, separator=',') => {

    /*csv download*/
    if (data.length === 0) {
        message.warn("NO such data. Please reset the search criteria.");
    } else {
        const cols = Object.keys(data[0]);
        let blobData = '\uFEFF'  // BOM head, make excel know it is csv.
        if (!removeColName) {
            blobData += cols.join(separator) + '\n';  // add column name

        }
        console.log('prepare to download. data is ', data);
        data.forEach(
            item => {
                const itemData = []
                cols.forEach(col => {
                    // console.log(ele, index)
                    const val = item[col] || '-';
                    itemData.push(`"${val}"`)
                })
                blobData += `${itemData.join(separator)}\n`;

            }
        );
        const export_uri = `data:text/csv;charset=utf-8,${encodeURIComponent(blobData)}`;
        const a = document.createElement('a');
        a.style.display = 'none';
        a.setAttribute('target', '_blank');
        a.setAttribute('download', fileName);
        a.href = export_uri;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    }
}

参数data为要导出的数据,要求格式为列表,列表元素为对象。如果data为空会报错。
当data不为空时,会以data的第一个元素的key值作为列名。默认是要输出列名的,如果不想在导出的文件中包含列名,可以将removeColName设置为True。
另外,默认情况下csv中每一行的分隔符是逗号,但其他的如制表符其实也可以。如果想使用除逗号之外的分隔符,可以将其传递给separator参数。

准备导出数据的部分并不复杂,其实就是将data中元素的每一个值挨个取出,用separator拼接在一起形成一个字符串,然后元素和元素之间(可以理解为行与行之间)用\n分隔即可。

!!注意:需要保证data中每一个元素的key相同,否则只会取第一个元素中包含的key做导出文件的列。

在导出内容整理好之后,就通过添加超链接节点的方式触发下载,也就是const export_uri = `data:text/csv;charset=utf-8,${encodeURIComponent(blobData)}`;及之后的代码。

plainExport

const plainExport = (data, fileName='export.txt') => {
    let blobData = data

    const export_uri = `data:text/plain;charset=utf-8,${encodeURIComponent(blobData)}`;
    const a = document.createElement('a');
    a.style.display = 'none';
    a.setAttribute('target', '_blank');
    a.setAttribute('download', fileName);
    a.href = export_uri;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);

}

逻辑更加简单,即“无脑地”将输入的参数进行导出。这里,要求data为字符串结构,由后台代码来控制每一行列分别是什么样子。比如在我的项目中,先将dataframe的多列拼接成由逗号分隔各列内容的单列,然后将其转为list,最后用换行符拼接成一个字符串。这样的字符串经由plainExport()导出,其形如csv,但添加了在csv中不太好操作的一些格式化内容,用以满足用户的需求:

# python
joined_series = None
for col_index in range(len(df.columns)):
    if col_index == 0:
        joined_series = "  "+df[df.columns[col_index]]  # first col, start with two space
    elif col_index == len(df.columns) -1:
        # last col, start with ",", no spaces
        joined_series += ","+df[df.columns[col_index]]
    else:
        # middle cols, start with ",....", "." is space
        joined_series += ",    " + df[df.columns[col_index]]

logger.debug("Join all columns of df is done.")

if joined_series is None:
    raise Exception(f"No columns can be got")

logger.debug(str(joined_series))
joined_series_list = joined_series.tolist()
return_content = "\n".join(joined_series_list)
return return_content

完整code

import { message } from 'antd';


const csvExport = (data, fileName='export.csv', removeColName = false, separator=',') => {

    /*csv download*/
    if (data.length === 0) {
        message.warn("NO such data. Please reset the search criteria.");
    } else {
        const cols = Object.keys(data[0]);
        let blobData = '\uFEFF'  // BOM head, make excel know it is csv.
        if (!removeColName) {
            blobData += cols.join(separator) + '\n';  // add column name

        }
        console.log('prepare to download. data is ', data);
        data.forEach(
            item => {
                const itemData = []
                cols.forEach(col => {
                    // console.log(ele, index)
                    const val = item[col] || '-';
                    itemData.push(`"${val}"`)
                })
                blobData += `${itemData.join(separator)}\n`;

            }
        );
        // console.log('prepare export', blobData);
        const export_uri = `data:text/csv;charset=utf-8,${encodeURIComponent(blobData)}`;
        const a = document.createElement('a');
        a.style.display = 'none';
        a.setAttribute('target', '_blank');
        a.setAttribute('download', fileName);
        a.href = export_uri;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    }


}


const plainExport = (data, fileName='export.txt') => {
    let blobData = data

    const export_uri = `data:text/plain;charset=utf-8,${encodeURIComponent(blobData)}`;
    const a = document.createElement('a');
    a.style.display = 'none';
    a.setAttribute('target', '_blank');
    a.setAttribute('download', fileName);
    a.href = export_uri;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);

}


export {
    csvExport,
    plainExport
}

你可能感兴趣的:(【utils】前端导出数据:csv与txt【2023-02-21】)