【问题标题】:Pasting excel data into a blank DataGridView - Index out of range exception将 excel 数据粘贴到空白 DataGridView - 索引超出范围异常
【发布时间】:2014-04-03 09:27:24
【问题描述】:

我有一个包含以下内容的 Excel 表格:

所以,我想要实现的是从 Excel 中复制它并将其粘贴到空白的 DataGridView 视图中。

这是我目前的代码:

private void PasteClipboard(DataGridView myDataGridView)
{
    DataObject o = (DataObject)Clipboard.GetDataObject();
    if (o.GetDataPresent(DataFormats.Text))
    {
        string[] pastedRows = Regex.Split(o.GetData(DataFormats.Text).ToString().TrimEnd("\r\n".ToCharArray()), "\r\n");
        foreach (string pastedRow in pastedRows)
        {
            string[] pastedRowCells = pastedRow.Split(new char[] { '\t' });
            using (DataGridViewRow myDataGridViewRow = new DataGridViewRow())
            {
                for (int i = 0; i < pastedRowCells.Length; i++)
                    myDataGridViewRow.Cells[i].Value = pastedRowCells[i];

                myDataGridView.Rows.Add(myDataGridViewRow);
            }
        }
    }
}

当代码运行时,我收到以下错误:

我是否在错误地处理手头的任务?

【问题讨论】:

    标签: c# excel winforms datagridview


    【解决方案1】:

    经过一番挖掘,我发现我必须先添加列,然后添加新行,获取新创建行的行索引,然后设置单元格值。

    这是更新后的代码:

    DataObject o = (DataObject)Clipboard.GetDataObject();
    if (o.GetDataPresent(DataFormats.Text))
    {
        if (myDataGridView.RowCount > 0)
            myDataGridView.Rows.Clear();
    
        if (myDataGridView.ColumnCount > 0)
            myDataGridView.Columns.Clear();
    
        bool columnsAdded = false;
        string[] pastedRows = Regex.Split(o.GetData(DataFormats.Text).ToString().TrimEnd("\r\n".ToCharArray()), "\r\n");
        foreach (string pastedRow in pastedRows)
        {
            string[] pastedRowCells = pastedRow.Split(new char[] { '\t' });
    
            if (!columnsAdded)
            {
                for (int i = 0; i < pastedRowCells.Length; i++)
                    myDataGridView.Columns.Add("col" + i, pastedRowCells[i]);
    
                columnsAdded = true;
                continue;
            }
    
            myDataGridView.Rows.Add();
            int myRowIndex = myDataGridView.Rows.Count - 1;
    
            using (DataGridViewRow myDataGridViewRow = myDataGridView.Rows[myRowIndex])
            {
                for (int i = 0; i < pastedRowCells.Length; i++)
                    myDataGridViewRow.Cells[i].Value = pastedRowCells[i];
            }
        }
    }
    

    }

    它正在工作:

    乐于接受批评和改进这一点的有用提示。 这段代码很慢...

    【讨论】:

    • 如何将多张工作表复制到 datagridview 中?
    • 太棒了,帮助很大。
    【解决方案2】:

    我知道这是几年后的事了,但我一直在寻找解决这个问题的方法,并找到了 BASA 对 Latheesan 代码的修改。它只是部分工作,所以修改它,我想为未来的浏览器添加这个解决方案:

    private void Paste(DataGridView d)
        {
            DataObject o = (DataObject)Clipboard.GetDataObject();
            if (o.GetDataPresent(DataFormats.StringFormat))
            {
                string[] pastedRows = Regex.Split(o.GetData(DataFormats.StringFormat).ToString().TrimEnd("\r\n".ToCharArray()), "\r");
                int j = 0;
                try { j = d.CurrentRow.Index; } catch { }
                foreach (string pastedRow in pastedRows)
                {
                    DataGridViewRow r = new DataGridViewRow();
                    r.CreateCells(d, pastedRow.Split(new char[] { '\t' }));
                    d.Rows.Insert(j, r);
                    j++;
                }
            }
        }
    

    【讨论】:

    • 它帮助了我。刚刚得到一个错误,DataGridView中应该有列
    • 出色的工作!
    【解决方案3】:

    完美代码在这里:(写入按钮)

    DataObject o = (DataObject)Clipboard.GetDataObject();
    if (o.GetDataPresent(DataFormats.Text))
    {
        if (myDataGridView.RowCount > 0)
            myDataGridView.Rows.Clear();
    
        if (myDataGridView.ColumnCount > 0)
            myDataGridView.Columns.Clear();
    
        bool columnsAdded = false;
        string[] pastedRows = Regex.Split(o.GetData(DataFormats.Text).ToString().TrimEnd("\r\n".ToCharArray()), "\r\n");
        int j=0;
        foreach (string pastedRow in pastedRows)
        {
            string[] pastedRowCells = pastedRow.Split(new char[] { '\t' });
    
            if (!columnsAdded)
            {
                for (int i = 0; i < pastedRowCells.Length; i++)
                    myDataGridView.Columns.Add("col" + i, pastedRowCells[i]);
    
                columnsAdded = true;
                continue;
            }
    
            myDataGridView.Rows.Add();
            int myRowIndex = myDataGridView.Rows.Count - 1;
    
            using (DataGridViewRow myDataGridViewRow = myDataGridView.Rows[j])
            {
                for (int i = 0; i < pastedRowCells.Length; i++)
                    myDataGridViewRow.Cells[i].Value = pastedRowCells[i];
            }
            j++;
        }
    }
    

    修改自Latheesan's code

    【讨论】:

    • 这与我的回答有何不同?它看起来也几乎相同......你只是复制并粘贴我的答案吗?
    • 不,先生。您的代码仅粘贴最后一行。我只是编辑 int j=0 并增加该值以粘贴复制的所有值
    • 您的编辑提供了哪些重大改进?
    【解决方案4】:

    定义你的gridview列,如果没有,你必须先定义列。

    private void PasteClipboard(DataGridView myDataGridView)
    {
        DataObject o = (DataObject)Clipboard.GetDataObject();
        if (o.GetDataPresent(DataFormats.Text))
        {
            string[] pastedRows = Regex.Split(o.GetData(DataFormats.Text).ToString().TrimEnd("\r\n".ToCharArray()), "\r\n");
            foreach (string pastedRow in pastedRows)
            {
                string[] pastedRowCells = pastedRow.Split(new char[] { '\t' });
                using (DataGridViewRow myDataGridViewRow = new DataGridViewRow())
                {
                    myDataGridViewRow = (DataGridViewRow) myDataGridView.RowTemplate.Clone();
                    for (int i = 0; i < pastedRowCells.Length; i++)
                        myDataGridViewRow.Cells[i].Value = pastedRowCells[i];
    
                    myDataGridView.Rows.Add(myDataGridViewRow);
                }
            }
        }
    }
    

    IF 未定义列

    private void PasteClipboard(DataGridView myDataGridView)
    {
        //Create COlumns in datagridView
        myDataGridView = new DataGridView();
        myDataGridView.Columns.Add("col1", "Col1");
        myDataGridView.Columns.Add("col2", "Col2");
        myDataGridView.Columns.Add("col3", "Col3");
        myDataGridView.Columns.Add("col4", "Col4");
    
        DataObject o = (DataObject)Clipboard.GetDataObject();
        if (o.GetDataPresent(DataFormats.Text))
        {
            string[] pastedRows = Regex.Split(o.GetData(DataFormats.Text).ToString().TrimEnd("\r\n".ToCharArray()), "\r\n");
            foreach (string pastedRow in pastedRows)
            {
                string[] pastedRowCells = pastedRow.Split(new char[] { '\t' });
                using (DataGridViewRow myDataGridViewRow = new DataGridViewRow())
                {
                    myDataGridViewRow = (DataGridViewRow) myDataGridView.RowTemplate.Clone();
                    for (int i = 0; i < pastedRowCells.Length; i++)
                        myDataGridViewRow.Cells[i].Value = pastedRowCells[i];
    
                    myDataGridView.Rows.Add(myDataGridViewRow);
                }
            }
        }
    }
    

    【讨论】:

    • 谢谢。我也得出了相同的解决方案。不定义列就不能添加新行。
    • 这就是我所说的,因为我不知道您是否早先定义了这些列,所以我为这两种情况提供了解决方案:)
    【解决方案5】:

    here 发布了一个非常好的解决方案:

    但是,需要更改一行:

     if (dgv.Rows.Count < (r + rowsInClipboard.Length))
                dgv.Rows.Add(r + rowsInClipboard.Length - dgv.Rows.Count);
    

    需要改成:

     if (dgv.Rows.Count < (r + rowsInClipboard.Length))
                dgv.Rows.Add(r + rowsInClipboard.Length+1 - dgv.Rows.Count);
    

    如果这一行没有变化,最后粘贴的行将不会传递给 SQL。

    【讨论】:

      【解决方案6】:

      如果您正在处理 Unicode,这里是粘贴到绑定到 DataGridView 的 DataTable 的代码

              DataObject o = (DataObject)Clipboard.GetDataObject();
              if (o.GetDataPresent(DataFormats.Text))
              {
                  string[] pastedRows = Regex.Split(o.GetText().TrimEnd("\r\n".ToCharArray()), "\r\n");
                  foreach (string pastedRow in pastedRows)
                  {
                      string[] pastedRowCells = pastedRow.Split(new char[] { '\t' });
                      var temp = dt1.NewRow();
                      for (int i = 0; i < pastedRowCells.Length; i++)
                          temp[i] = pastedRowCells[i];
                      dt1.Rows.Add(temp);
                  }
              }
      

      【讨论】:

        【解决方案7】:

        我刚刚修改了@Latheesan's code,如下是最短的版本。

        DataObject o = (DataObject)Clipboard.GetDataObject();
        
        if (o.GetDataPresent(DataFormats.Text))
        {
            if (myDataGridView.Rows.Count > 0)
                myDataGridView.Rows.Clear();
            if (myDataGridView.Columns.Count > 0)
                myDataGridView.Columns.Clear();
        
            bool columnsAdded = false;
            string[] pastedRows = Regex.Split(o.GetData(DataFormats.Text).ToString().TrimEnd("\r\n".ToCharArray()), "\r\n");
            foreach (string pastedRow in pastedRows)
            {
                string[] pastedRowCells = pastedRow.Split(new char[] { '\t' });
        
                if (!columnsAdded)
                {
                    for (int i = 0; i < pastedRowCells.Length; i++)
                        myDataGridView.Columns.Add("col" + i, pastedRowCells[i]);
        
                    columnsAdded = true;
                    continue;
                }
        
                myDataGridView.Rows.Add(pastedRowCells);
        
                //***You don't need following lines, use just above line. ***
        
                //myDataGridView.Rows.Add();
                //int myRowIndex = myDataGridView.Rows.Count - 1;
        
                //using (DataGridViewRow myDataGridViewRow = myDataGridView.Rows[myRowIndex])
                //{
                //    for (int i = 0; i < pastedRowCells.Length; i++)
                //        myDataGridViewRow.Cells[i].Value = pastedRowCells[i];
                //}
            }
        }
        

        【讨论】:

        • 一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助。 (至少有一个用户标记了这篇文章,大概是因为他们认为应该删除没有解释的答案。或者他们对你复制另一个答案而不提供归属链接并不真正感到兴奋。)
        • 感谢内森,但这是我的第一条评论。你只会说我会做什么。这是一种粗鲁的行为。我想。我没有在评论中说这是一个新的和最好的解决方案。我审查并测试了@Latheesan 的代码。它不起作用!我分享了一个更好的...
        • 这不是问题;问题更多在于您的回答没有(充分)清楚地解释为什么 Latheesan 的代码不起作用以及您的代码为什么起作用,而且正如我所提到的,它的归属也相当草率。
        【解决方案8】:

        //列数错误已修复:://

        using System.Linq;
        
        DataTable xDataTable = new DataTable();
        DataObject XClipboardDat = (DataObject)Clipboard.GetDataObject();
        
        if (XClipboardDat.GetDataPresent(DataFormats.Text))
        {
            string[] XClipboardRows = Regex.Split(XClipboardDat.GetData(DataFormats.Text).ToString(), @"[\r\n]+").Where(y => !string.IsNullOrEmpty(y.ToString())).ToArray();
        
            IEnumerable<string[]> XDatRowCol = XClipboardRows.Select(xRow => Regex.Split(xRow, @"[\t]+").Where(y => !string.IsNullOrEmpty(y.ToString())).ToArray());
        
            int ColNum = XDatRowCol.Select(XDatRow => XDatRow.Length).ToArray().Max<int>();
        
            for (int i = 0; i < ColNum; i++) { xDataTable.Columns.Add(); }
        
            foreach(string[] XDatRow in XDatRowCol) { xDataTable.Rows.Add(XDatRow); }
        
            dataGridView2.DataSource = xDataTable;
         }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多