C#将excel文本格式的数据添加到剪贴板

时间:2013-04-02 13:03:05

标签: c# excel format cell clipboard

在C#中,我需要将数据网格行复制到excel。由于连续中的某些值是双精度数,因此可以使用“-Infinity”值。

我尝试将行复制为DataFormats.UnicodeTextDataFormats.Text,但这给了我输出“#NAME?”,我应该看到“-Infinity”(因为excel由于标准单元格格式,在“=”中的减号之前自动插入“-Infinity”。

在粘贴之前将单元格格式设置为“Text”时,Excel不会在“=”之前自动插入“-Infinity”。顺便说一下,我不需要用excel中的double值进行任何计算,所以文本格式对我来说没问题。

所以我的问题是如何将数据复制到剪贴板并将其粘贴到Excel中,同时将单元格格式设置为“text”。

3 个答案:

答案 0 :(得分:8)

从Raw Clipboard查看器开始,您可以看到复制

Excel Snip

到剪贴板导致Excel向剪贴板抛出大量不同的格式。

enter image description here

其中大多数没有帮助,但其中一些是excel内部的,这意味着它(几乎)将保证数据与复制的数据相同。如果我是你,我可能会以 XML SpreadSheet 为目标,或者你感觉勇敢 Biff12 ,这也是xml(但是压缩)。与普通文本相比,这将使您可以更好地控制粘贴。

作为示例,上面的剪辑导致

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:html="http://www.w3.org/TR/REC-html40">
 <Styles>
  <Style ss:ID="Default" ss:Name="Normal">
   <Alignment ss:Vertical="Bottom"/>
   <Borders/>
   <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
   <Interior/>
   <NumberFormat/>
   <Protection/>
  </Style>
  <Style ss:ID="s63">
   <NumberFormat ss:Format="@"/>
  </Style>
 </Styles>
 <Worksheet ss:Name="Sheet1">
  <Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="2"
   ss:DefaultRowHeight="15">
   <Row>
    <Cell><Data ss:Type="Number">1</Data></Cell>
    <Cell><Data ss:Type="Number">2</Data></Cell>
   </Row>
   <Row>
    <Cell><Data ss:Type="String">Test</Data></Cell>
    <Cell ss:StyleID="s63"><Data ss:Type="String" x:Ticked="1">-Infinity</Data></Cell>
   </Row>
  </Table>
 </Worksheet>
</Workbook>

所以看得更深一点......当我尝试使用Clipboard.SetData将xml写入剪贴板时,看起来.Net剪贴板类做了一些奇怪而不是那么美妙的事情 Clipboard Data

剪贴板以一堆箔条开始。这当然导致Excel拒绝剪贴板内容。

为了解决这个问题,我使用Windows API(user32)调用来处理剪贴板

    [DllImport("user32.dll", SetLastError = true)]
    static extern uint RegisterClipboardFormat(string lpszFormat);
    [DllImport("user32.dll")]
    static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool CloseClipboard();
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool OpenClipboard(IntPtr hWndNewOwner);

    private static void XMLSpreadSheetToClipboard(String S)
    {
        var HGlob = Marshal.StringToHGlobalAnsi(S);
        uint Format = RegisterClipboardFormat("XML SpreadSheet");
        OpenClipboard(IntPtr.Zero);
        SetClipboardData(Format, HGlob);
        CloseClipboard();
        Marshal.FreeHGlobal(HGlob);
    }

答案 1 :(得分:1)

感谢您的信息。经过一些搜索,我发现你可以使用.Net剪贴板类,但你不能将String传递给SetData()。这对我有用:

System::Text::UTF8Encoding^ enc = gcnew System::Text::UTF8Encoding();
System::Windows::Forms::Clipboard::SetData("XML Spreadsheet", gcnew MemoryStream(enc->GetBytes(data)));

答案 2 :(得分:0)

win32 api解决方案不适用于我。我发生了随机崩溃。 以下代码也可以正常工作,也可以与Unicode字符一起使用。

var xml = File.ReadAllText(@"..\..\SampleData\Clipboard-Example3.xml");

var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
var dataObject = new DataObject();
dataObject.SetData("XML SpreadSheet", stream);

Clipboard.Clear();
Clipboard.SetDataObject(dataObject);