如何将JavaScript的2D数组复制到剪贴板并粘贴到Excel中?

12

示例2D数组:

var arr = [
  ["Mike", "Cane", 23],
  ["Jeff", "Meyers", 46],
  ["Thomas", "Bush", 67]
]

如何将一个二维数组复制到剪贴板,然后将其粘贴到Excel电子表格中? 行和列应保持与数组中的相同。 它应该像在Excel中选择一系列单元格然后将其粘贴回去一样工作。

4个回答

10
很简单,只需添加制表符\t来分隔列,以及换行符\n来分隔行。
使用以下代码:
const excelData = arr
  .map(lines => lines.join("\t"))
  .join("\n");

const arr = [
  ["Mike", "Cane", 23],
  ["Jeff", "Meyers", 46],
  ["Thomas", "Bush", 67]
];

document.getElementById('convert').addEventListener('click', () => {
  const excelData = arr
    .map(lines => lines.join("\t"))
    .join("\n");
 
  document.getElementById('excel').textContent = excelData;
});
<textarea id="excel" cols="30" rows="6"></textarea><br>
<button id="convert">Make Excel Clipboard data</button>

运行代码段,点击按钮,将文本复制粘贴到Excel中进行测试。


我最终结合了你和@Niklas E.的答案。你从2D数组到字符串的映射更简单,但我需要一种解决方案,可以在按下ctrl+c后直接从代码中复制数组。你的解决方案完美地解决了这个问题,但在我的情况下需要一个额外的步骤和一个“丢弃”的文本区域。谢谢! - oemera
@NiklasE。仅仅“查看”代码并不是更好的选择,这会使代码变得更加简单。而我所说的“不必要的复杂性”并不是指使用/[\n\t]+/g正则表达式进行清理,而是指循环。你的代码完全可接受。当然,for循环是有效且可接受的,我只是指出在Javascript中可以用更简单的方式来实现。你不需要编辑它,没问题的。 - Christos Lytras
非常感谢!顺便说一下,您拼错了“separate”。 - Geoff Hom
1
@GeoffHom 不用谢,感谢您的纠正。我已经编辑了我的答案并更正了打字错误。您也可以编辑问题/答案并更正任何拼写错误/错误。 - Christos Lytras
@ChristosLytras:谢谢你的信息!我不习惯使用SO,除了阅读答案。 - Geoff Hom
显示剩余3条评论

5

这个解决方案非常棒。它使用(类似于逗号分隔值的)换行符表示新行,制表符表示新单元格。将这样的文本粘贴到Excel、OpenOffice / LibreOffice Calc电子表格中,它会将其识别为多个单元格。它在Google Docs上也可以使用。

function copy2DToClipboard(array) {
  var csv = '', row, cell;
  for (row = 0; row < array.length; row++) {
    for (cell = 0; cell < array[row].length; cell++) {
      csv += (array[row][cell]+'').replace(/[\n\t]+/g, ' ');
      if (cell+1 < array[row].length) csv += '\t';
    }
    if (row+1 < array.length) csv += '\n';
  }
  copyTextToClipboard(csv);
}

// copied from https://dev59.com/fHRC5IYBdhLWcg3wJNcN
function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;

  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    // console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    // console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    console.error('Async: Could not copy text: ', err);
  });
}

测试:

function onTest() {
  const arr = [
    ["Mike", "Cane", 23],
    ["Jeff", "Meyers", 46],
    ["Thomas", "Bush", 67]
  ];
  copy2DToClipboard(arr);
  document.getElementById('test').innerText = 'Copied!';
}

function copy2DToClipboard(array) {
  var csv = '', row, cell;
  for (row = 0; row < array.length; row++) {
    for (cell = 0; cell < array[row].length; cell++) {
      csv += (array[row][cell]+'').replace(/[\n\t]+/g, ' ');
      if (cell+1 < array[row].length) csv += '\t';
    }
    if (row+1 < array.length) csv += '\n';
  }
  copyTextToClipboard(csv);
}

// copied from https://dev59.com/fHRC5IYBdhLWcg3wJNcN
function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;
  
  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    // console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    // console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    console.error('Async: Could not copy text: ', err);
  });
}
<button onclick="onTest()" id="test">Copy to clipboard.</button>

编辑:

此解决方案不支持带有内部换行或制表符的单元格。非ASCII Unicode字符可能会导致某些电子表格程序出现问题。

同时参见JavaScript如何复制到剪贴板?


谢谢,这正是我想要的!由于我可以使用ES6+,将2D数组转换为字符串的过程可以简化,就像@Christos Lytras所展示的那样。 - oemera
@oemera 好的,我想为其他用户编辑我的答案,他们可能会看到你的问题,以获得更简单的ES6+解决方案(如果你同意的话)。但我想保留.replace(/[\n\t]+/g, ' ')。我认为这部分非常重要。 - Niklas E.

1

我想提一下,现在有一种更简单的方法可以将内容复制到剪贴板上 - 你不再需要创建一个文本区域来复制数据。

这个例子使用了 @christos-lytra 的数组映射。

  const arr = [
    ['Mike', 'Cane', 23],
    ['Jeff', 'Meyers', 46],
    ['Thomas', 'Bush', 67],
  ];

  const excelData = arr.map(lines => lines.join('\t')).join('\n');

  navigator.clipboard.writeText(excelData);

-1

1
不幸的是,这不是一个选项。该过程应该非常快速和直接。此外,数组的内容大多非常小。保存和导入JSON将会是太大的努力。但这个JavaScript还是很好的了解,谢谢。 - oemera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接