You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CSV导出中保留HTML格式文本?求替代方案

解决带HTML格式的赛事报告导出问题

一、CSV格式下处理HTML排版

CSV本身是纯文本格式,要让<p>、<br>这类标签呈现对应的换行效果,需要先把HTML解析为带换行的纯文本,再传入react-csv-downloader。

1. 写一个HTML转格式化纯文本的工具函数

这个函数会处理常见的排版标签,把HTML结构转成CSV能识别的换行:

const htmlToFormattedText = (html) => {
  if (!html) return '';
  // 替换<br>为换行符
  let text = html.replace(/<br\s*\/?>/gi, '\n');
  // 替换<p>标签为换行开头,</p>为换行结尾
  text = text.replace(/<p\s*.*?>/gi, '\n');
  text = text.replace(/<\/p>/gi, '\n');
  // 移除其他HTML标签
  text = text.replace(/<[^>]+>/g, '');
  // 去除多余的连续换行
  return text.replace(/\n{2,}/g, '\n').trim();
};

2. 在导出组件中应用这个函数

修改你的ExportReport.jsx,在构造CSV数据时转换对应的字段:

import CSVReactDownloader from 'react-csv-downloader';

const ExportReport = ({ report }) => {
  // 处理带HTML的字段
  const formattedAthleteNotes = htmlToFormattedText(report.athleteAttackNotes);
  const formattedOpponentNotes = htmlToFormattedText(report.opponentAttackNotes);

  const data = [
    {
      // 其他字段...
      '运动员进攻笔记': formattedAthleteNotes,
      '对手进攻笔记': formattedOpponentNotes,
    },
  ];

  const columns = [
    // 其他列定义...
    { id: '运动员进攻笔记', displayName: '运动员进攻笔记' },
    { id: '对手进攻笔记', displayName: '对手进攻笔记' },
  ];

  return (
    <CSVReactDownloader
      filename="赛事报告"
      data={data}
      columns={columns}
    >
      <button>导出CSV</button>
    </CSVReactDownloader>
  );
};

export default ExportReport;

这样导出的CSV里,原HTML的分段和换行就会以纯文本换行的形式呈现,用Excel或文本编辑器打开时能看到正确的排版。

二、更适合复杂排版的替代导出方案

如果CSV的排版能力不够满足需求,推荐以下几种格式:

1. Excel(XLSX)格式

Excel单元格支持原生换行,能完美保留分段结构,推荐用xlsx库实现:

import * as XLSX from 'xlsx';

const exportToExcel = (report) => {
  const formattedAthleteNotes = htmlToFormattedText(report.athleteAttackNotes);
  const formattedOpponentNotes = htmlToFormattedText(report.opponentAttackNotes);

  const worksheetData = [
    ['字段', '内容'],
    ['运动员进攻笔记', formattedAthleteNotes],
    ['对手进攻笔记', formattedOpponentNotes],
    // 其他字段...
  ];

  const worksheet = XLSX.utils.aoa_to_sheet(worksheetData);
  // 设置单元格自动换行
  worksheet['!cols'] = [{ wch: 50 }, { wch: 80 }];
  Object.keys(worksheet).forEach(key => {
    if (key.startsWith('B')) {
      worksheet[key].s = { alignment: { wrapText: true } };
    }
  });

  const workbook = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(workbook, worksheet, '赛事报告');
  XLSX.writeFile(workbook, '赛事报告.xlsx');
};

// 在组件中使用
<button onClick={() => exportToExcel(report)}>导出Excel</button>

2. PDF格式

如果需要导出带格式的文档,react-pdf可以直接将HTML转换为PDF元素,保留更丰富的排版:

import { Document, Page, Text, View, StyleSheet, PDFDownloadLink } from '@react-pdf/renderer';

const styles = StyleSheet.create({
  page: { padding: 30 },
  section: { marginBottom: 15 },
  title: { fontSize: 16, fontWeight: 'bold', marginBottom: 5 },
  content: { fontSize: 14, whiteSpace: 'pre-wrap' },
});

const ReportPDF = ({ report }) => {
  const formattedAthleteNotes = htmlToFormattedText(report.athleteAttackNotes);
  const formattedOpponentNotes = htmlToFormattedText(report.opponentAttackNotes);

  return (
    <Document>
      <Page size="A4" style={styles.page}>
        <View style={styles.section}>
          <Text style={styles.title}>运动员进攻笔记</Text>
          <Text style={styles.content}>{formattedAthleteNotes}</Text>
        </View>
        <View style={styles.section}>
          <Text style={styles.title}>对手进攻笔记</Text>
          <Text style={styles.content}>{formattedOpponentNotes}</Text>
        </View>
        {/* 其他内容 */}
      </Page>
    </Document>
  );
};

// 在组件中使用
<PDFDownloadLink document={<ReportPDF report={report} />} fileName="赛事报告.pdf">
  {({ blob, url, loading, error }) => loading ? '导出中...' : '导出PDF'}
</PDFDownloadLink>

3. Markdown格式

如果需要导出可编辑的纯文本格式,可以先把HTML转成Markdown,再导出:

// 可以用html-to-markdown库简化转换
import { convert } from 'html-to-markdown';

const exportToMarkdown = (report) => {
  const athleteMd = convert(report.athleteAttackNotes);
  const opponentMd = convert(report.opponentAttackNotes);

  const mdContent = `# 赛事报告

## 运动员进攻笔记
${athleteMd}

## 对手进攻笔记
${opponentMd}

// 其他字段...
`;

  // 创建下载链接
  const blob = new Blob([mdContent], { type: 'text/markdown' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = '赛事报告.md';
  a.click();
  URL.revokeObjectURL(url);
};

// 在组件中使用
<button onClick={() => exportToMarkdown(report)}>导出Markdown</button>

内容的提问来源于stack exchange,提问作者Stephen Scott Moore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:00:12