4

在 C# 中,我需要将数据网格行复制到 Excel。因为一行中的某些值是双精度值,所以 " -Infinity" 值是可能的。

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

当我Text在粘贴之前将单元格格式化为“”时,excel不会在“ =”之前自动插入“ -Infinity”。顺便说一句,我不需要对 excel 中的双精度值进行任何计算,所以文本格式对我来说就可以了。

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

4

3 回答 3

9

从原始剪贴板查看器开始,您可以看到复制

Excel 截图

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

在此处输入图像描述

其中大多数没有帮助,但其中一些是 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 类似乎做了一些奇怪而不是那么美妙的事情剪贴板数据

剪贴板从一堆谷壳开始。这当然会导致 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);
    }
于 2013-04-02T14:24:30.197 回答
2

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

System::Text::UTF8Encoding^ enc = gcnew System::Text::UTF8Encoding();
System::Windows::Forms::Clipboard::SetData("XML Spreadsheet", gcnew MemoryStream(enc->GetBytes(data)));
于 2015-02-21T04:32:13.013 回答
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);
于 2020-03-27T13:58:56.813 回答