如何使用C#将CSV数据复制到Windows剪贴板

35

我想要达成的目标

  • 我的应用程序生成一些表格数据
  • 我希望用户能够启动Excel并单击“粘贴”将数据作为单元格放置在Excel中
  • Windows接受一种称为“CommaSeparatedValue”的格式,可与其API一起使用,因此这似乎是可能的
  • 将原始文本放入剪贴板是有效的,但尝试使用此格式则不起作用
  • 注意:我可以从剪贴板正确检索CSV数据,我的问题是关于将CSV数据粘贴到剪贴板上。

我所尝试过但没有奏效的方法

Clipboard.SetText()

System.Windows.Forms.Clipboard.SetText(  
  "1,2,3,4\n5,6,7,8", 
  System.Windows.Forms.TextDataFormat.CommaSeparatedValue
  );

Clipboard.SetData()

:将数据存储到剪贴板中。

System.Windows.Forms.Clipboard.SetData(
  System.Windows.Forms.DataFormats.CommaSeparatedValue,
  "1,2,3,4\n5,6,7,8", 
  );

两种情况下都会将某些内容放置到剪贴板中,但粘贴到Excel中时会显示为一格垃圾文本:“–§žý;pC¦yVk²ˆû”。

更新1:使用SetText()的解决方法

正如BFree的答案所示,使用TextDataFormat的SetText()可以作为解决方法。

System.Windows.Forms.Clipboard.SetText(  
  "1\t2\t3\t4\n5\t6\t7\t8", 
  System.Windows.Forms.TextDataFormat.Text
  );

我已经尝试过这个方法,并确认现在可以正确地将内容粘贴到Excel和Word中。每次粘贴时,它都会作为带有单元格的表格而不是纯文本进行。

仍然好奇为什么逗号分隔值(CommaSeparatedValue)无法使用。

4个回答

43

在.NET Framework中,DataFormats.CommaSeparatedValue被放置在剪贴板上作为Unicode文本。但正如http://www.syncfusion.com/faq/windowsforms/faq_c98c.aspx#q899q所提到的,Excel期望CSV数据是一个UTF-8的内存流(很难说是.NET还是Excel造成了不兼容)。

我在自己的应用程序中想出的解决方案是同时将表格数据以制表符分隔的文本和CSV内存流的形式放置在剪贴板上。这样目标应用程序就可以以其首选格式获取数据。记事本和Excel更喜欢制表符分隔的文本,但你可以通过“粘贴特殊...”命令来测试强制Excel抓取CSV数据。

这是一些示例代码(请注意,在此使用了WPF命名空间的WinForms等效项):

// Generate both tab-delimited and CSV strings.
string tabbedText = //...
string csvText = //...

// Create the container object that will hold both versions of the data.
var dataObject = new System.Windows.DataObject();

// Add tab-delimited text to the container object as is.
dataObject.SetText(tabbedText);

// Convert the CSV text to a UTF-8 byte stream before adding it to the container object.
var bytes = System.Text.Encoding.UTF8.GetBytes(csvText);
var stream = new System.IO.MemoryStream(bytes);
dataObject.SetData(System.Windows.DataFormats.CommaSeparatedValue, stream);

// Copy the container object to the clipboard.
System.Windows.Clipboard.SetDataObject(dataObject, true);

你认为那些没有使用.NET的人该如何做到这一点?如果你愿意深入了解应用程序域/封送/COM对象规则,可能是有可能的吗?也许我会像其他答案一样坚持使用“/t”。 - Groostav
Excel不需要流,直接将UTF8字节放入其中即可。不处理MemoryStream可能会导致内存泄漏。 - Wouter

7
请使用制表符(Tab键)代替逗号,例如:
Clipboard.SetText("1\t2\t3\t4\t3\t2\t3\t4", TextDataFormat.Text);

我刚刚亲自测试了一下,对我有效。


我尝试了CSV方法,但也无法使其工作 - 看起来使用制表符是正确的方法。 - Charlie
很高兴知道在这方面,Excel更加宽容对待制表符。 - Justin Dearing
1
注意这一点,因为Excel会尝试将以*、+、-等运算符开头的值解释为公式。我不确定CSV是否也会遇到这个问题。 - Oliver Bock
CSV 无法解决这个问题。 :( - CAD bloke

4

我曾经成功地使用 \t(参见 BFree 的回答)作为列分隔符,使用 \n 作为行分隔符,将内容粘贴到 Excel 中。


0

我通过使用CSV库(KBCsv)将数据写入临时文件夹中的CSV文件,然后使用Process.Start()在Excel中打开它,从而成功解决了格式问题。一旦在Excel中,格式化部分就容易多了,可以直接从Excel中复制粘贴。

string filePath = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";

using (var streamWriter = new StreamWriter(filePath))
using (CsvWriter csvWriter = new CsvWriter(streamWriter))
{
    // optional header
    csvWriter.WriteRecord(new List<string>(){"Heading1", "Heading2", "YouGetTheIdea" });

    csvWriter.ValueSeparator = ',';
    foreach (var thing in YourListOfThings ?? new List<OfThings>())
    {
        if (thing != null)
        {
            List<string> csvLine = new List<string>
                                         {
                                             thing.Property1, thing.Property2, thing.YouGetTheIdea
                                         };

            csvWriter.WriteRecord(csvLine);
        }
    }
}

Process.Start(filePath);

自行编写错误处理和日志记录。


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