Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DataGridView复制粘贴区分空白单元格和跳过的单元格?_C#_Datagridview_Copy_Copy Paste_Paste - Fatal编程技术网

C# DataGridView复制粘贴区分空白单元格和跳过的单元格?

C# DataGridView复制粘贴区分空白单元格和跳过的单元格?,c#,datagridview,copy,copy-paste,paste,C#,Datagridview,Copy,Copy Paste,Paste,我已经实现了一个C#DataGridView并构建了复制/粘贴功能,如其他文章所述: // Copy Code DataObject d = ws.GetClipboardContent(); if (d != null) { Clipboard.SetDataObject(d); } // //粘贴代码 字符串s=Clipboard.GetText(); 字符串sWithoutSlashR

我已经实现了一个C#DataGridView并构建了复制/粘贴功能,如其他文章所述:

        // Copy Code
        DataObject d = ws.GetClipboardContent();
        if (d != null)
        {
            Clipboard.SetDataObject(d);
        }
//

//粘贴代码
字符串s=Clipboard.GetText();
字符串sWithoutSlashR=s.Replace(“\r”,”);//如果存在,请删除\r\n
string[]line=sWithoutSlashR.Split('\n');
int row=ws.CurrentCell.RowIndex;
布尔值allGood=true;
foreach(行中的字符串行)
{
int col=ws.CurrentCell.ColumnIndex;
string[]cells=line.Split('\t');
int cellsSelected=cells.Length;
对于(int i=0;i
如果复制源单元格中有空白,而粘贴目标单元格不是空的,则会出现问题。假设正在复制三个单元格,其内容分别为“T”、“T”和“T”(即引号仅用于可读性,中间的单元格为空白)。如果用户选择所有三个单元格,则复制的内容是:“T\r\n\r\nT”。粘贴此选项将用空白覆盖中间单元格,这很好

但是,如果用户仅选择带有控制键的第一个和第三个单元格,则复制的内容是相同的:“T\r\n\r\nT”。因为用户没有选择空的中间单元格,所以不应该粘贴空的中间单元格,但确实如此

由于复制内容相同,如何区分选定的空单元格和跳过的单元格


迈克

向约翰大声喊叫,感谢他把我引向正确的方向!以下是我的解决方案:

全局变量:

DataGridViewSelectedCellCollection copySource;
copySource = ws.SelectedCells;
我的DataGridView在下面的示例中命名为ws。在通过CTRL+C或上下文菜单访问的复制命令中,我填充全局变量:

DataGridViewSelectedCellCollection copySource;
copySource = ws.SelectedCells;
粘贴命令如下所示:

        if (copySource == null) return;     // nothing to paste, so leave 
        if (copySource.Count == 0) return;  // nothing to paste, so leave

        // find top left Source cell
        int topSourceRow = copySource[0].RowIndex;
        int leftSourceCol = copySource[0].ColumnIndex;
        foreach(DataGridViewCell cell in copySource)
        {
            if (cell.RowIndex < topSourceRow) topSourceRow = cell.RowIndex;
            if (cell.ColumnIndex < leftSourceCol) leftSourceCol = cell.ColumnIndex;
        }

        // find top left destination cell
        int topDestRow = ws.SelectedCells[0].RowIndex;
        int leftDestCol = ws.SelectedCells[0].ColumnIndex;

        // paste cells
        Boolean allGood = true;
        foreach (DataGridViewCell cell in copySource)
        {
            // check if we have run off the edge of the grid
            // todo: expand if statement to add type checks if needed
            if (topDestRow + cell.RowIndex - topSourceRow >= ws.Rows.Count || leftDestCol + cell.ColumnIndex - leftSourceCol >= ws.Columns.Count)
            {
                // do not paste, set flag to show warning
                allGood = false;
            }
            else
            {
                // perform paste
                ws.Rows[topDestRow + cell.RowIndex - topSourceRow].Cells[leftDestCol + cell.ColumnIndex - leftSourceCol].Value = cell.Value.ToString();
            }
        }
        if (!allGood)
        {
            // todo: display warning to user that not all cells were pasted
        }
if(copySource==null)返回;//没有要粘贴的内容,所以请离开
如果(copySource.Count==0)返回;//没有要粘贴的内容,所以请离开
//查找左上角的源单元格
int topSourceRow=copySource[0]。行索引;
int leftSourceCol=copySource[0]。ColumnIndex;
foreach(copySource中的DataGridViewCell单元格)
{
如果(cell.RowIndex=ws.Rows.Count | | leftDestCol+cell.ColumnIndex-leftSourceCol>=ws.Columns.Count)
{
//不粘贴,将标志设置为显示警告
一切都好=错误;
}
其他的
{
//执行粘贴
ws.Rows[topDestRow+cell.RowIndex-topSourceRow].Cells[leftDestCol+cell.ColumnIndex-leftSourceCol].Value=cell.Value.ToString();
}
}
如果(!好的)
{
//todo:向用户显示未粘贴所有单元格的警告
}
初始冒烟测试表明,空白单元格被复制并正确覆盖目标单元格。复制不连续单元的行为符合预期——拷贝源的中间的跳过单元不包含在粘贴中。

这种方法的假设是,用户选择了目标单元格的左上角进行粘贴,我认为这是合理的

如果粘贴离开右边缘或下边缘,则粘贴可以粘贴的单元格。跳过边缘的单元格,并向用户显示警告消息。您的错误检查要求可能会有所不同


在我的应用程序中,我将保留我的原始代码,以便将源单元格复制到操作系统剪贴板,以便用户能够灵活地从我的应用程序复制到Excel或其他目的地。

经过长时间的讨论后,我想澄清一些事情。我下面的解决方案与Mike Paisner的答案非常相似,我对他找到可行的解决方案表示赞赏。干得好…请投我一票

关于使用操作系统的copy命令,它将根据您的需要工作。在Mike Paisner的原始问题中,代码使用操作系统的copy命令复制网格中的“选定”单元格。使用操作系统的复制命令时,粘贴会覆盖未选择“空”值的单元格

考虑到操作系统如何使用在
DataGridView
中选择的单元格构造复制命令,这是正确的。使用原始post中的post代码,其工作方式如上所述,用空值覆盖未选定的单元格。如果您想“忽略”空值而不覆盖这些单元格,那么在原始代码中进行简单的检查应该可以解决这个问题。类似于

if (col < ws.ColumnCount && row < ws.RowCount) {
  if (cells[i].ToString() != "") {   // <-- added check for empty (non-selected) cells
    ws.Rows[row].Cells[col].Value = cells[i].ToString();
  }
  else {
     // empty cell value
   }
}
在本例中,我们希望找到集合中编号为“最低”的列和行。我们可以循环遍历集合,或者,由于集合是可枚举的,我们可以简单地根据列索引对集合进行排序,然后获取第一个items列索引。然后按行索引对其排序,并获取行索引中的第一项。它可能看起来像

Index   cellValue
  0       R3C3
  1       R1C4
  2       R3C1
  3       R5C2
int colIndex = copyCollection.Cast<DataGridViewCell>().OrderBy(c => c.ColumnIndex).First().ColumnIndex;
int rowIndex = copyCollection.Cast<DataGridViewCell>().OrderBy(c => c.RowIndex).First().RowIndex;
int colDif = ws.CurrentCell.ColumnIndex - colIndex
int rowDif = ws.CurrentCell.RowIndex - rowIndex;
然后
colDif
将是0-1=-1…
rowDif
将是5-1=4。这些将是我们需要“添加”到选定单元格集合中的每个单元格以映射到要粘贴到的适当单元格中的“神奇”数字

示例:内部