JS 在 Excel 中 # 后构建 CSV 中断
JS built CSV breaking after # in Excel
我正在通过 JavaScript 构建 CSV,一些单元格值包含主题标签和其他特殊字符。我特别注意到主题标签充当文件的硬停止。我一直无法在网上找到解决方案,也没有真正看到这个具体问题。我已尝试 \uFEFF
修复,但无济于事。下面是我用来构建 CSV 的函数。
export const buildCSV = (headers, data) => {
if (!headers && !data) return;
let csvContent = "data:text/csv;charset=UTF-8,";
if (headers) {
csvContent += headers.join(",") + "\r\n";
}
if (data) {
data.forEach(row => {
csvContent += row.join(",") + "\r\n";
});
}
return encodeURI(csvContent);
};
作为参考,目前,150 # content
等值在打开 CSV 文件时将显示为 150
,其余行将被截断。
提前感谢任何花时间提供答案的人!
从这里的答案中挑选线索 JavaScript blob filename without link。
下面给出的代码的最小复制似乎有效。它依赖于 HTML5 中的下载属性。所以,不支持旧的浏览器。但是如果你想要那种支持,上面 link 有更多的答案你可以查看。
<script>
const buildCSV = (headers, data) => {
if (!headers && !data) return;
let csvContent = "";
if (headers) {
csvContent += headers.join(",") + "\r\n";
}
if (data) {
data.forEach(row => {
csvContent += row.join(",") + "\r\n";
});
}
return csvContent;
}
function downloadFile()
{
function download(data, fileName) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
blob = new Blob([data], {type: "text/csv"}),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
var data = buildCSV(['header1','header2','header3'],[['150#content','rowvalue1','rowvalue2']]),
fileName = "myfile.csv";
download(data, fileName);
}
</script>
<body>
<a href="" onclick="downloadFile()" >Download</a>
</body>
我通过进行此切换设法解决了问题:
const encodedURI = encodeURI(csvContent);
const fixedEncodedURI = encodedURI.replaceAll('#', '%23');
return fixedEncodedURI;
在 运行encodeURI 之前执行转换导致结果为“%23”,而不是将其正确转换回主题标签。根据 MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#Description),encodeURI
函数不会转义主题标签(在其他字符中,但我没有注意到其他字符有问题)。手动编码后,一旦下载并在 Excel.
中打开,它们就会转换回主题标签
TKoL 创建了一个 fiddle 显示了 encodeURIComponent
的使用导致了期望的输出。需要注意的是,当我 运行 遇到尝试使用此功能的问题时,必须对初始代码进行以下更改,否则将导致下载失败:
let csvContent = "";
other code...
return "data:text/csv;charset=utf-8," + encodeURIComponent(csvContent);
感谢所有提供潜在解决方案的人!
我正在通过 JavaScript 构建 CSV,一些单元格值包含主题标签和其他特殊字符。我特别注意到主题标签充当文件的硬停止。我一直无法在网上找到解决方案,也没有真正看到这个具体问题。我已尝试 \uFEFF
修复,但无济于事。下面是我用来构建 CSV 的函数。
export const buildCSV = (headers, data) => {
if (!headers && !data) return;
let csvContent = "data:text/csv;charset=UTF-8,";
if (headers) {
csvContent += headers.join(",") + "\r\n";
}
if (data) {
data.forEach(row => {
csvContent += row.join(",") + "\r\n";
});
}
return encodeURI(csvContent);
};
作为参考,目前,150 # content
等值在打开 CSV 文件时将显示为 150
,其余行将被截断。
提前感谢任何花时间提供答案的人!
从这里的答案中挑选线索 JavaScript blob filename without link。
下面给出的代码的最小复制似乎有效。它依赖于 HTML5 中的下载属性。所以,不支持旧的浏览器。但是如果你想要那种支持,上面 link 有更多的答案你可以查看。
<script>
const buildCSV = (headers, data) => {
if (!headers && !data) return;
let csvContent = "";
if (headers) {
csvContent += headers.join(",") + "\r\n";
}
if (data) {
data.forEach(row => {
csvContent += row.join(",") + "\r\n";
});
}
return csvContent;
}
function downloadFile()
{
function download(data, fileName) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
blob = new Blob([data], {type: "text/csv"}),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
var data = buildCSV(['header1','header2','header3'],[['150#content','rowvalue1','rowvalue2']]),
fileName = "myfile.csv";
download(data, fileName);
}
</script>
<body>
<a href="" onclick="downloadFile()" >Download</a>
</body>
我通过进行此切换设法解决了问题:
const encodedURI = encodeURI(csvContent);
const fixedEncodedURI = encodedURI.replaceAll('#', '%23');
return fixedEncodedURI;
在 运行encodeURI 之前执行转换导致结果为“%23”,而不是将其正确转换回主题标签。根据 MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#Description),encodeURI
函数不会转义主题标签(在其他字符中,但我没有注意到其他字符有问题)。手动编码后,一旦下载并在 Excel.
TKoL 创建了一个 fiddle 显示了 encodeURIComponent
的使用导致了期望的输出。需要注意的是,当我 运行 遇到尝试使用此功能的问题时,必须对初始代码进行以下更改,否则将导致下载失败:
let csvContent = "";
other code...
return "data:text/csv;charset=utf-8," + encodeURIComponent(csvContent);
感谢所有提供潜在解决方案的人!