【问题标题】:How to paste CSV data to Windows Clipboard with C#如何使用 C# 将 CSV 数据粘贴到 Windows 剪贴板
【发布时间】:2010-09-24 16:49:50
【问题描述】:

我想要完成的事情

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

我尝试过的方法不起作用

剪贴板.SetText()

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

剪贴板.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 的回答所示,SetTextTextDataFormat 可以作为一种解决方法

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

我已经尝试过,并确认现在粘贴到 Excel 和 Word 中可以正常工作。在每种情况下,它都会粘贴为包含单元格而不是纯文本的表格。

仍然好奇 CommaSeparatedValue 为什么工作。

【问题讨论】:

    标签: c# windows csv clipboard paste


    【解决方案1】:

    .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 上的人如何做到这一点有什么想法吗?如果您愿意一头扎进 appdomain/marshalling/com-object 规则,是否有可能?也许我会按照其他答案坚持/t
    【解决方案2】:

    使用制表符代替逗号。即:

    Clipboard.SetText("1\t2\t3\t4\t3\t2\t3\t4", TextDataFormat.Text);
    

    我自己测试了一下,它对我有用。

    【讨论】:

    • 我尝试了 CSV 方法,但也无法让它工作 - 看起来使用标签是要走的路。
    • 很高兴知道 excel 在这方面对选项卡更宽容。
    • 注意这一点,因为 Excel 会尝试将以 *、+、- 等运算符开头的值解释为公式。我不确定 CSV 是否也能解决这个问题。
    • CSV 无法解决这个问题。 :(
    【解决方案3】:

    我已成功使用 \t(参见 BFree 的答案)作为列分隔符和 \n 作为行分隔符粘贴到 Excel。

    【讨论】:

      【解决方案4】:

      通过使用 CSV 库 (KBCsv) 将数据写入临时文件夹中的 CSV 文件,然后在 Excel 中使用 Process.Start() 打开它,我在解决格式问题方面取得了最大的成功。一旦它在 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);
      

      BYO 错误处理和记录。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-13
        • 2017-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-31
        相关资源
        最近更新 更多