【问题标题】:Paste to Excel From DataGridView从 DataGridView 粘贴到 Excel
【发布时间】:2013-09-17 18:30:50
【问题描述】:

我想从 dataGridView 复制一个单元格区域,然后将该数据粘贴到 MS Excel 中。我可以复制数据并粘贴到 MS Word 或记事本中,但不能复制到 Excel 中。有很多从 Excel 复制并粘贴到 DataGridView 的示例,但反之则不然。

private void frm_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.KeyCode == Keys.C)
    {
        this.dataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText;

        if (this.dataGridView1.GetCellCount(DataGridViewElementStates.Selected) > 0)
        {
            try
            {
                DataObject d = dataGridView1.GetClipboardContent();
                Clipboard.SetDataObject(d);
            }

            catch (System.Runtime.InteropServices.ExternalException)
            {
                MessageBox.Show("Could Not Copy To Clipboard");
            }
        }
    }
}

有没有办法粘贴到excel中?我一直在努力寻找解决方案。

编辑

在使用dataGridViews尝试其他一些程序后出现,您可以在选择dataGridView中的一组单元格后默认复制并粘贴到excel或其他程序中。我现在无法确定是否是 DGV 中不受支持的数据或我在属性管理器中更改的 DGV 属性,或者我只需要关闭并重新打开 excel,因为出现了一些错误。

【问题讨论】:

  • 粘贴时会发生什么?无数据、错误数据、格式错误的数据?您在剪贴板上实际获得的通常是格式化的文本。也许格式与 Excel 所期望的不匹配。您可能必须向后工作,自己格式化文本,然后手动将其放在剪贴板上。
  • 忘了说,不会粘贴任何数据。我可以将数据粘贴到 word 和记事本中。
  • 好吧,我在尝试了其他一些带有 DataGridViews 的程序后才意识到,它们可以被复制并粘贴到 excel 中,而无需添加任何代码来专门这样做。因此,为什么关于这个主题的问题或答案如此之少。我认为这可能是我在 DataGridView 属性管理器上更改的一些设置。

标签: c# excel


【解决方案1】:

我不能说这将如何与您的网格对齐,但这里有一个将格式化文本放在剪贴板上的示例。这是为了粘贴到 Excel 中而编写的:

StringBuilder sb = new StringBuilder();
for (Int32 r = Selection.r1; r <= Selection.r2; r++)
{
    if (Rows[r].Visible)
    {
        if (!String.IsNullOrEmpty(sb.ToString()))
            sb.Append(Environment.NewLine);
        for (Int32 c = Selection.c1; c <= Selection.c2; c++)
        {
            if (!sb.ToString().EndsWith(Environment.NewLine) &&
                !String.IsNullOrEmpty(sb.ToString()) &&
                !sb.ToString().EndsWith("\t"))
                sb.Append("\t");
            if (String.IsNullOrEmpty(this[r, c] as String))
                sb.Append(" ");
            else
                sb.Append(this[r, c].ToString());
        }
    }
}

if (sb.Length > 0)
    ClipboardEx.SetTextThreadSafe(sb.ToString());

注意:Selection 是我的网格对突出显示的内容的引用,this 是用于获取单元格中数据的单元格引用。

基本上,它试图构建一个类似这样的文本块:

R1C1\tR1C2\tR1C3\tR1C4\n
R2C1\tR2C2\tR2C3\tR2C4\n
R3C1\tR3C2\tR3C3\tR3C4\n

制表符 (\t) 告诉它向右移动一列,换行符 (\n) 告诉它向下移动一行。这是一种非常标准的格式。如果您在此处复制并粘贴您的网格,Excel 会给您什么。

【讨论】:

    【解决方案2】:

    好吧,我一直在寻找答案。

    如果我将 Clipboard.SetDataObject(d); 更改为 Clipboard.SetData(DataFormats.Html, d);,这允许我将选定的单元格区域粘贴到 Excel。

    【讨论】:

    • 请注意,HTML 格式可能无法与旧版本的 Excel 向后兼容。
    • @DonBoitnott 有更好的方法吗?
    • @AntonioBakula 这不是标准的剪贴板格式,而且是个坏主意。请参阅:*.com/questions/329918/…
    【解决方案3】:
    public class MyDataGridView : DataGridView    
    {    
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]    
        protected override bool ProcessDataGridViewKey(KeyEventArgs e)    
        {    
            switch (e.KeyCode)    
            {    
                case Keys.Insert:    
                case Keys.C:    
                    return this.ProcessInsertKey(e.KeyData);    
                default:    
                    break;    
            }    
            return base.ProcessDataGridViewKey(e);    
        }    
    
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]    
        protected new bool ProcessInsertKey(Keys keyData)    
        {    
            if ((((keyData & (Keys.Alt | Keys.Control | Keys.Shift)) == Keys.Control) ||    
                (((keyData & (Keys.Alt | Keys.Control | Keys.Shift)) == (Keys.Control | Keys.Shift))    
                && ((keyData & Keys.KeyCode) == Keys.C)))    
                && (this.ClipboardCopyMode != DataGridViewClipboardCopyMode.Disable))    
            {    
                DataObject clipboardContent = this.GetClipboardContent();    
                if (clipboardContent != null)    
                {     
                    Clipboard.SetText(clipboardContent.GetData(DataFormats.UnicodeText).ToString());    
                    return true;    
                }    
            }    
            return false;    
        }    
    }
    

    您可以使用此自定义控件。

    【讨论】:

      【解决方案4】:

      为什么不简单地这样做 [无需检查剪贴板,因为您实际上是在使用 CTRL-C ]

      private void frm_KeyDown(object sender, KeyEventArgs e)
          {
              if (e.Control && e.KeyCode == Keys.C)
              {
                  dataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
                  dataGridView1.SelectAll();
                  Clipboard.SetDataObject(dataGridView1.GetClipboardContent());               
              }
          }
      

      【讨论】: