Reputation: 24116
I have an excel sheet with the following:
So, what I am trying to achieve is copy this from Excel and paste it into a blank DataGridView
view.
This is the code I have so far:
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);
}
}
}
}
When the code runs, I am getting the following error:
Am I approaching this task at hand incorrectly?
Upvotes: 13
Views: 37064
Reputation: 33
The code below allows to paste clipboard data starting from the selected cell, ignores if data exceeds the current column count and adds subsequent rows if required to accommodate for extra pasted rows
private void dataBatch_KeyUp(object sender, KeyEventArgs e)
{
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.V)
{
var gridView = (DataGridView)sender;
DataObject o = (DataObject)Clipboard.GetDataObject();
if (o.GetDataPresent(DataFormats.StringFormat))
{
string[] pastedRows = Regex.Split(o.GetData(DataFormats.StringFormat).ToString().TrimEnd(Environment.NewLine.ToCharArray()), Environment.NewLine);
DataGridViewCell firstSelectedCell;
try
{
firstSelectedCell = gridView.SelectedCells.Count > 0 ? gridView.SelectedCells[0] : (gridView.Rows.Count > 0 ? ((DataGridViewRow)(gridView.Rows[0])).Cells[0] : throw new Exception(""));
}
catch { return; }
int initialColumnIndex = firstSelectedCell.ColumnIndex;
var rowCounter = 1;
var rowCount = pastedRows.Count();
foreach (string pastedRow in pastedRows)
{
var cellData = pastedRow.Split('\t');
foreach (var cd in cellData)
{
firstSelectedCell.Value = cd;
firstSelectedCell.Selected = true;
if (firstSelectedCell.ColumnIndex < gridView.Columns.Count - 1)
{
firstSelectedCell = gridView[firstSelectedCell.ColumnIndex + 1, firstSelectedCell.RowIndex];
}
else
{
break;
}
}
if (rowCounter < rowCount)
{
if (firstSelectedCell.RowIndex >= gridView.Rows.Count - 1)
{
gridView.Rows.Add();
}
firstSelectedCell = gridView[initialColumnIndex, firstSelectedCell.RowIndex + 1];
rowCounter++;
}
}
}
}
}
Upvotes: 0
Reputation: 3459
In case you are dealing with Unicode here is the code to paste to a DataTable that is binded to a the DataGridView
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);
}
}
Upvotes: 0
Reputation: 103
I know it's some years later, but I was looking for a solution for this problem and found BASA's modification of Latheesan's code. It only worked partially, so modifying it, I would like to add this solution for future browsers:
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++;
}
}
}
Upvotes: 5
Reputation: 1
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;
}
Upvotes: -1
Reputation: 21
A really nice solution was posted here:
But, one line needs to be changed:
if (dgv.Rows.Count < (r + rowsInClipboard.Length))
dgv.Rows.Add(r + rowsInClipboard.Length - dgv.Rows.Count);
needs to be changed to:
if (dgv.Rows.Count < (r + rowsInClipboard.Length))
dgv.Rows.Add(r + rowsInClipboard.Length+1 - dgv.Rows.Count);
If this line isn't changes, the last row pasted will not be passed to SQL.
Upvotes: 2
Reputation: 169
Perfect Code here: (write in button)
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++;
}
}
Modified from Latheesan's code.
Upvotes: 5
Reputation: 1
I've just modified @Latheesan's code as below which is the shortest version.
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];
//}
}
}
Upvotes: -1
Reputation: 24116
After some digging around, I found that I have to add columns first, then add a new row, get the row index of the newly created row, and then set the cell values.
Here's the updated code:
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];
}
}
}
}
And here it is working:
Happy to accept criticisms and useful tips on improving this. This code is quite slow...
Upvotes: 10
Reputation: 2144
Have your gridview columns defined, if not you have to define the columns first.
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 not definced columns
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);
}
}
}
}
Upvotes: 3