private static Dictionary <CellLocation, DataGridViewGenericCell> GetSelectedCells(DataGridView dataGridView) { Dictionary <CellLocation, DataGridViewGenericCell> selectedCells = new Dictionary <CellLocation, DataGridViewGenericCell>(); foreach (DataGridViewCell dataGridViewCell in dataGridView.SelectedCells) { CellLocation cellPosition = new CellLocation(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); selectedCells.Add(cellPosition, DataGridViewHandler.CopyCellDataGridViewGenericCell(dataGridView, cellPosition.ColumnIndex, cellPosition.RowIndex)); } return(selectedCells); }
private static Dictionary <CellLocation, DataGridViewGenericCell> GetCellsFromStack(DataGridView dataGridView, Dictionary <CellLocation, DataGridViewGenericCell> undoCells) { Dictionary <CellLocation, DataGridViewGenericCell> redoCells = new Dictionary <CellLocation, DataGridViewGenericCell>(); foreach (CellLocation cellLocation in undoCells.Keys) { CellLocation cellPosition = new CellLocation(cellLocation.ColumnIndex, cellLocation.RowIndex); redoCells.Add(cellPosition, DataGridViewHandler.CopyCellDataGridViewGenericCell(dataGridView, cellPosition.ColumnIndex, cellPosition.RowIndex)); } return(redoCells); }
public static void UndoDataGridView(DataGridView dataGridView) { if (IsDoingUndoRedo) { return; } if (dataGridView.CurrentCell == null) { return; } CellLocation currentCell = DataGridViewHandler.GetCurrentCellLocation(dataGridView.CurrentCell); if (dataGridView.TopLeftHeaderCell.Tag == null) { return; } if (dataGridView.TopLeftHeaderCell.Tag.GetType() != typeof(DataGridViewGenericData)) { return; } DataGridViewGenericData undoAndRedo = (DataGridViewGenericData)dataGridView.TopLeftHeaderCell.Tag; if (undoAndRedo.UndoCellsStack.Count > 0) { Dictionary <CellLocation, DataGridViewGenericCell> undoCells = undoAndRedo.UndoCellsStack.Pop(); Dictionary <CellLocation, DataGridViewGenericCell> redoCells = GetCellsFromStack(dataGridView, undoCells); PushToRedoStack(dataGridView, redoCells); IsDoingUndoRedo = true; //needs to be after PushToRedoStack or it will return NuberOfItemsToEdit = undoCells.Count; IsClipboardActive = true; foreach (var cell in undoCells) { DataGridViewHandler.SetCellDataGridViewGenericCell(dataGridView, cell.Key.ColumnIndex, cell.Key.RowIndex, cell.Value, true); } NuberOfItemsToEdit = 0; IsClipboardActive = false; } DataGridViewHandler.SetCurrentCellLocation(dataGridView, currentCell); IsDoingUndoRedo = false; }
public static void PasteDataGridViewSelectedCellsFromClipboard( DataGridView dataGridView, int leftColumnOverwrite, int rightColumnOverwrite, int topRowOverwrite, int buttomRowOverwrite, bool removeTag, out bool textBoxSelectionCanRestore, out int textBoxSelectionStart, out int textBoxSelectionLength) { textBoxSelectionStart = 0; textBoxSelectionLength = 0; textBoxSelectionCanRestore = false; #region Html Format // Try to process as html format (data from excel) since it keeps the row information intact, instead of assuming // a new row for every new line if we just process it as text String HtmlFormat = Clipboard.GetData("HTML Format") as String; List <List <string> > rowContents = new List <List <string> >(); if (HtmlFormat != null) { try { // Remove html tags to just extract row information and store it in rowContents System.Text.RegularExpressions.Regex TRregex = new System.Text.RegularExpressions.Regex(@"<( )*tr([^>])*>", System.Text.RegularExpressions.RegexOptions.IgnoreCase); System.Text.RegularExpressions.Regex TDregex = new System.Text.RegularExpressions.Regex(@"<( )*td([^>])*>", System.Text.RegularExpressions.RegexOptions.IgnoreCase); System.Text.RegularExpressions.Match trMatch = TRregex.Match(HtmlFormat); while (!string.IsNullOrWhiteSpace(trMatch.Value)) { int rowStart = trMatch.Index + trMatch.Length; int rowEnd = HtmlFormat.IndexOf("</tr>", rowStart, StringComparison.InvariantCultureIgnoreCase); System.Text.RegularExpressions.Match tdMatch = TDregex.Match(HtmlFormat, rowStart, rowEnd - rowStart); List <string> rowContent = new List <string>(); while (!string.IsNullOrWhiteSpace(tdMatch.Value)) { int cellStart = tdMatch.Index + tdMatch.Length; int cellEnd = HtmlFormat.IndexOf("</td>", cellStart, StringComparison.InvariantCultureIgnoreCase); string cellContent = HtmlFormat.Substring(cellStart, cellEnd - cellStart); cellContent = System.Text.RegularExpressions.Regex.Replace(cellContent, @"<( )*br( )*>", "\r\n", System.Text.RegularExpressions.RegexOptions.IgnoreCase); cellContent = System.Text.RegularExpressions.Regex.Replace(cellContent, @"<( )*li( )*>", "\r\n - ", System.Text.RegularExpressions.RegexOptions.IgnoreCase); cellContent = System.Text.RegularExpressions.Regex.Replace(cellContent, @"<( )*div([^>])*>", "", System.Text.RegularExpressions.RegexOptions.IgnoreCase); cellContent = System.Text.RegularExpressions.Regex.Replace(cellContent, @"<( )*code([^>])*>", "", System.Text.RegularExpressions.RegexOptions.IgnoreCase); cellContent = System.Text.RegularExpressions.Regex.Replace(cellContent, @"<( )*/code([^>])*>", "", System.Text.RegularExpressions.RegexOptions.IgnoreCase); cellContent = System.Text.RegularExpressions.Regex.Replace(cellContent, @"<( )*p([^>])*>", "\r\n\r\n", System.Text.RegularExpressions.RegexOptions.IgnoreCase); if (!cellContent.StartsWith("<B>")) //Don't paste Row Header { //cellContent = cellContent.Replace(" ", " "); cellContent = System.Net.WebUtility.HtmlDecode(cellContent); rowContent.Add(cellContent); } tdMatch = tdMatch.NextMatch(); } if (rowContent.Count > 0) { rowContents.Add(rowContent); } trMatch = trMatch.NextMatch(); } } catch { rowContents.Clear(); } } #endregion #region Text format if (rowContents.Count == 0) { // Clipboard is not in html format, read as text String CopiedText = Clipboard.GetText(); String[] lines = CopiedText.Split('\n'); foreach (string line in lines) { List <string> rowContent = new List <string>(line.Split('\t')); if (rowContent.Count > 0) { rowContents.Add(rowContent); } } } #endregion #region Paste into Edit cell if (IsCurrentCellTextBoxAndInEditMode(dataGridView)) { if (rowContents.Count >= 1) { string clipboardText = ""; foreach (List <string> textsInLine in rowContents) { string clipboardLine = ""; foreach (string text in textsInLine) { clipboardLine = clipboardLine + (string.IsNullOrWhiteSpace(clipboardLine) ? "" : " ") + text; } clipboardText = clipboardText + (string.IsNullOrWhiteSpace(clipboardText) ? "" : "\r\n") + clipboardLine; } Clipboard.SetText(clipboardText); } TextBox textBox = dataGridView.EditingControl as TextBox; if (textBox != null) { textBox.Paste(); TextBoxGetSelction(textBox, out textBoxSelectionCanRestore, out textBoxSelectionStart, out textBoxSelectionLength); textBoxSelectionCanRestore = true; } return; //Can return - don't need push to stach, Edit cell did push to stacj } #endregion // ----------------------------------------------------------------------------- // Put the feach data to cells // ----------------------------------------------------------------------------- Stack <CellLocation> selectedCells = new Stack <CellLocation>(); #region Find all - SelectedCells - and - topRow and leftColumn - int topRow = int.MaxValue; int leftColumn = int.MaxValue; foreach (DataGridViewCell dataGridViewCell in dataGridView.SelectedCells) { topRow = Math.Min(topRow, dataGridViewCell.RowIndex); leftColumn = Math.Min(leftColumn, dataGridViewCell.ColumnIndex); selectedCells.Push(new CellLocation(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex)); } int iRow = topRow; #endregion #region Add Rows if needed if (dataGridView.AllowUserToAddRows) { // DataGridView's rowCount has one extra row (the temporary new row) if (iRow + rowContents.Count > dataGridView.Rows.Count - 1) { int iNumNewRows = iRow + rowContents.Count - dataGridView.Rows.Count + 1; // Simply add to a new row to the datagridview if it is not binded to a datasource if (dataGridView.DataSource == null) { //dataGridView.Rows.Add(iNumNewRows); //This will change the selected cell for (int i = 0; i < iNumNewRows; i++) { dataGridView.Rows.Add(); } dataGridView.ClearSelection(); //Remove the selection and select it back after } // Otherwise, add rows to binded data source else { try { BindingSource bindingSource = dataGridView.DataSource as BindingSource; if (bindingSource != null) { // This is important!! // Cancel Edit before adding new entries into bindingsource // If the UI is currently adding a new line (you have your cursor on the last time) // You will System.InvalidOperationException bindingSource.CancelEdit(); for (int i = 0; i < iNumNewRows; i++) { Object obj = bindingSource.AddNew(); dataGridView.ClearSelection(); } } } catch { // failed adding row to binding data source // It was okay for my application to ignore the error } } } } #endregion #region New rows added, and selection forgoten. Need to reselect if (dataGridView.SelectedCells.Count == 0) { while (selectedCells.Count > 0) { CellLocation cell = selectedCells.Pop(); dataGridView[cell.ColumnIndex, cell.RowIndex].Selected = true; } } #endregion //Paste one clipboard "cell/text" to all selected (Only one text to more than one selected cell) //Paste many clipbaord "cell/text" to selected fields (Paste to more than one selected cell) //Paste many clipbaord "cell/text" bases on current location (Paste to one selected cell) Dictionary <CellLocation, DataGridViewGenericCell> undoCells = new Dictionary <CellLocation, DataGridViewGenericCell>(); #region Count rows and columns in selctions List <int> columnsSelected = new List <int>(); List <int> rowsSelected = new List <int>(); foreach (CellLocation cellLocationCount in selectedCells) { if (!columnsSelected.Contains(cellLocationCount.ColumnIndex)) { columnsSelected.Add(cellLocationCount.ColumnIndex); } if (!rowsSelected.Contains(cellLocationCount.RowIndex)) { rowsSelected.Add(cellLocationCount.RowIndex); } } #endregion int columnConentsCount = 0; if (rowContents.Count > 0) { columnConentsCount = rowContents[0].Count; } #region Paste one clipboard "cell/text" to all selected (Only one text to more than one selected cell) #region Paste - Source: Nothing selected - nothing to do if (rowContents.Count == 0 && columnConentsCount == 0) { //Nothing found } #endregion #region Paste - Sourec: One Cell Selected (rowContents.Count == 1 && columnConentsCount == 1) else if (rowContents.Count == 1 && columnConentsCount == 1) { NuberOfItemsToEdit = dataGridView.SelectedCells.Count; IsClipboardActive = true; foreach (DataGridViewCell dataGridViewCell in dataGridView.SelectedCells) { String cellContent = rowContents[0][0]; try { if (!dataGridViewCell.ReadOnly || (dataGridViewCell.ColumnIndex >= leftColumnOverwrite && dataGridViewCell.ColumnIndex <= rightColumnOverwrite && dataGridViewCell.RowIndex >= topRowOverwrite && dataGridViewCell.RowIndex <= buttomRowOverwrite) ) { //Rememebr in the current value in cell before changed so we can "ReDo" in current DataGridView CellLocation cellPosition = new CellLocation(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); undoCells.Add(cellPosition, DataGridViewHandler.CopyCellDataGridViewGenericCell(dataGridView[dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex])); DataGridViewHandler.SetCellValue(dataGridView, dataGridViewCell, Convert.ChangeType(cellContent, dataGridViewCell.ValueType)); if (removeTag) { DataGridViewHandler.SetCellStatusSwichStatus(dataGridView, dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, SwitchStates.Undefine); } dataGridView.InvalidateCell(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); } } catch { } } NuberOfItemsToEdit = 0; IsClipboardActive = false; } #endregion #region Paste - One row, and multimple columns, Only cell selected / one row from clipboard to multiple rows else if ( rowContents.Count == 1 && columnConentsCount > 1 && //One row, and multimple columns columnsSelected.Count > 1 && rowsSelected.Count >= 1) //Only cell selected { if (columnConentsCount != columnsSelected.Count) { KryptonMessageBox.Show("Can't paste selection. Can only paste selection when have selected equal numbers of columns.\r\n" + "Columns selected for copy: " + columnConentsCount + "\r\n" + "Columns selected for paste: " + columnsSelected.Count, "Can't paste selected text", MessageBoxButtons.OK, MessageBoxIcon.Warning, showCtrlCopy: true); return; } NuberOfItemsToEdit = columnsSelected.Count * rowsSelected.Count; IsClipboardActive = true; columnsSelected.Sort(); for (int columnIndex = 0; columnIndex < rowContents[0].Count; columnIndex++) { String cellContent = rowContents[0][columnIndex]; //Row content will always be 1 int columnIndexPaste = columnsSelected[columnIndex]; foreach (DataGridViewCell dataGridViewCell in dataGridView.SelectedCells) { if (dataGridViewCell.ColumnIndex == columnIndexPaste) { try { if (!dataGridViewCell.ReadOnly || (dataGridViewCell.ColumnIndex >= leftColumnOverwrite && dataGridViewCell.ColumnIndex <= rightColumnOverwrite && dataGridViewCell.RowIndex >= topRowOverwrite && dataGridViewCell.RowIndex <= buttomRowOverwrite) ) { //Rememebr in the current value in cell before changed so we can "ReDo" in current DataGridView CellLocation cellPosition = new CellLocation(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); undoCells.Add(cellPosition, DataGridViewHandler.CopyCellDataGridViewGenericCell(dataGridViewCell)); DataGridViewHandler.SetCellValue(dataGridView, dataGridViewCell, Convert.ChangeType(cellContent, dataGridViewCell.ValueType)); if (removeTag) { DataGridViewHandler.SetCellStatusSwichStatus(dataGridView, dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, SwitchStates.Undefine); } dataGridView.InvalidateCell(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); } } catch { } } } } NuberOfItemsToEdit = 0; IsClipboardActive = false; } #endregion #region Paste - one column from clipboard to multiple columns / Only cell selected else if (rowContents.Count > 1 && columnConentsCount == 1 && //One column, and multimple rows !(columnsSelected.Count == 1 && rowsSelected.Count == 1)) //Only cell selected { if (rowContents.Count != rowsSelected.Count) { KryptonMessageBox.Show("Can't paste selection. Can only paste selection when have selected equal numbers of rows.\r\n" + "Rows selected for copy: " + rowContents.Count + "\r\n" + "Rows selected for paste: " + rowsSelected.Count, "Can't paste selected text", MessageBoxButtons.OK, MessageBoxIcon.Warning, showCtrlCopy: true); return; } NuberOfItemsToEdit = columnsSelected.Count * rowsSelected.Count; IsClipboardActive = true; rowsSelected.Sort(); for (int rowIndex = 0; rowIndex < rowContents.Count; rowIndex++) { String cellContent = rowContents[rowIndex][0]; foreach (DataGridViewCell dataGridViewCell in dataGridView.SelectedCells) { int columnIndexPaste = rowsSelected[rowIndex]; if (dataGridViewCell.RowIndex == columnIndexPaste) { try { if (!dataGridViewCell.ReadOnly || (dataGridViewCell.ColumnIndex >= leftColumnOverwrite && dataGridViewCell.ColumnIndex <= rightColumnOverwrite && dataGridViewCell.RowIndex >= topRowOverwrite && dataGridViewCell.RowIndex <= buttomRowOverwrite) ) { //Rememebr in the current value in cell before changed so we can "ReDo" in current DataGridView CellLocation cellPosition = new CellLocation(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); undoCells.Add(cellPosition, DataGridViewHandler.CopyCellDataGridViewGenericCell(dataGridViewCell)); DataGridViewHandler.SetCellValue(dataGridView, dataGridViewCell, Convert.ChangeType(cellContent, dataGridViewCell.ValueType)); if (removeTag) { DataGridViewHandler.SetCellStatusSwichStatus(dataGridView, dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex, SwitchStates.Undefine); } dataGridView.InvalidateCell(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); } } catch { } } } } NuberOfItemsToEdit = 0; IsClipboardActive = false; } #endregion #region Paste - rest else { NuberOfItemsToEdit = columnsSelected.Count * rowsSelected.Count; IsClipboardActive = true; foreach (List <string> rowContent in rowContents) { int iCol = leftColumn; foreach (string cellContent in rowContent) { try { bool cellOk = false; if (dataGridView.SelectedCells.Count == 1) { cellOk = true; } else { foreach (DataGridViewCell dataGridViewCell in dataGridView.SelectedCells) { if (dataGridViewCell.ColumnIndex == iCol && dataGridViewCell.RowIndex == iRow) { cellOk = true; } } } if (cellOk) { if (iCol < dataGridView.Columns.Count) { DataGridViewCell cell = dataGridView[iCol, iRow]; //if (!cell.ReadOnly) if (!cell.ReadOnly || (cell.ColumnIndex >= leftColumnOverwrite && cell.ColumnIndex <= rightColumnOverwrite && cell.RowIndex >= topRowOverwrite && cell.RowIndex <= buttomRowOverwrite) ) { //Rememebr in the current value in cell before changed so we can "ReDo" in current DataGridView CellLocation cellPosition = new CellLocation(iCol, iRow); undoCells.Add(cellPosition, DataGridViewHandler.CopyCellDataGridViewGenericCell(dataGridView, iCol, iRow)); DataGridViewHandler.SetCellValue(dataGridView, cell, Convert.ChangeType(cellContent, cell.ValueType)); if (removeTag) { DataGridViewHandler.SetCellStatusSwichStatus(dataGridView, cell.ColumnIndex, cell.RowIndex, SwitchStates.Undefine); } dataGridView.InvalidateCell(iCol, iRow); } } } } catch { } iCol++; } iRow++; if (iRow >= dataGridView.Rows.Count) { break; } } NuberOfItemsToEdit = 0; IsClipboardActive = false; dataGridView.ResumeLayout(); } #endregion #endregion //CAN BE REMOVED foreach (CellLocation cellLocation in undoCells.Keys) dataGridView[cellLocation.ColumnIndex, cellLocation.RowIndex].Selected = true; //Already done, can be removed after check PushToUndoStack(dataGridView, undoCells); }