/// <summary> /// Copy data from Clipboard and put on grid. /// /// Currently ReoGrid supports the following types of source from the clipboard. /// - Data from another ReoGrid instance /// - Plain/Unicode Text from any Windows Applications /// - Tabbed Plain/Unicode Data from Excel or similar applications /// /// When data copied from another ReoGrid instance, and the destination range /// is bigger than the source, ReoGrid will try to repeat putting data to fill /// the destination range entirely. /// /// Todo: Copy border and cell style from Excel. /// </summary> public bool Paste() { if (IsEditing) { this.controlAdapter.EditControlPaste(); } else { // Paste method will always perform action to do paste // do nothing if in readonly mode if (this.HasSettings(WorksheetSettings.Edit_Readonly) // or selection is empty || this.selectionRange.IsEmpty) { return(false); } try { this.controlAdapter.ChangeCursor(CursorStyle.Busy); PartialGrid partialGrid = null; string clipboardText = null; #if WINFORM || WPF DataObject data = Clipboard.GetDataObject() as DataObject; if (data != null) { partialGrid = data.GetData(ClipBoardDataFormatIdentify) as PartialGrid; if (data.ContainsText()) { clipboardText = data.GetText(); } } #elif ANDROID #endif // WINFORM || WPF if (partialGrid != null) { #region Partial Grid Pasting int startRow = selectionRange.Row; int startCol = selectionRange.Col; int rows = partialGrid.Rows; int cols = partialGrid.Columns; int rowRepeat = 1; int colRepeat = 1; if (selectionRange.Rows % partialGrid.Rows == 0) { rows = selectionRange.Rows; rowRepeat = selectionRange.Rows / partialGrid.Rows; } if (selectionRange.Cols % partialGrid.Columns == 0) { cols = selectionRange.Cols; colRepeat = selectionRange.Cols / partialGrid.Columns; } var targetRange = new RangePosition(startRow, startCol, rows, cols); if (!RaiseBeforePasteEvent(targetRange)) { return(false); } if (targetRange.EndRow >= this.rows.Count || targetRange.EndCol >= this.cols.Count) { // TODO: paste range overflow // need to notify user-code to handle this return(false); } // check any intersected merge-range in partial grid // bool cancelPerformPaste = false; if (partialGrid.Cells != null) { try { #region Check repeated intersected ranges for (int rr = 0; rr < rowRepeat; rr++) { for (int cc = 0; cc < colRepeat; cc++) { partialGrid.Cells.Iterate((row, col, cell) => { if (cell.IsMergedCell) { for (int r = startRow; r < cell.MergeEndPos.Row - cell.InternalRow + startRow + 1; r++) { for (int c = startCol; c < cell.MergeEndPos.Col - cell.InternalCol + startCol + 1; c++) { int tr = r + rr * partialGrid.Rows; int tc = c + cc * partialGrid.Columns; var existedCell = cells[tr, tc]; if (existedCell != null) { if ( // cell is a part of merged cell (existedCell.Rowspan == 0 && existedCell.Colspan == 0) // cell is merged cell || existedCell.IsMergedCell) { throw new RangeIntersectionException(selectionRange); } // cell is readonly else if (existedCell.IsReadOnly) { throw new CellDataReadonlyException(cell.InternalPos); } } } } } return(Math.Min(cell.Colspan, (short)1)); }); } } #endregion // Check repeated intersected ranges } catch (Exception ex) { cancelPerformPaste = true; // raise event to notify user-code there is error happened during paste operation if (OnPasteError != null) { OnPasteError(this, new RangeOperationErrorEventArgs(selectionRange, ex)); } } } if (!cancelPerformPaste) { DoAction(new SetPartialGridAction(new RangePosition( startRow, startCol, rows, cols), partialGrid)); } #endregion // Partial Grid Pasting } else if (!string.IsNullOrEmpty(clipboardText)) { #region Plain Text Pasting var arrayData = RGUtility.ParseTabbedString(clipboardText); int rows = Math.Max(selectionRange.Rows, arrayData.GetLength(0)); int cols = Math.Max(selectionRange.Cols, arrayData.GetLength(1)); // by bzquan expand rows of worksheet if (this.RowCount < rows) { this.RowCount = rows + 1; } var targetRange = new RangePosition(selectionRange.Row, selectionRange.Col, rows, cols); if (!RaiseBeforePasteEvent(targetRange)) { return(false); } if (this.controlAdapter != null) { var actionSupportedControl = this.controlAdapter.ControlInstance as IActionControl; if (actionSupportedControl != null) { actionSupportedControl.DoAction(this, new SetRangeDataAction(targetRange, arrayData)); } } #endregion // Plain Text Pasting } } catch (Exception ex) { // raise event to notify user-code there is error happened during paste operation //if (OnPasteError != null) //{ // OnPasteError(this, new RangeOperationErrorEventArgs(selectionRange, ex)); //} this.NotifyExceptionHappen(ex); } finally { this.controlAdapter.ChangeCursor(CursorStyle.Selection); RequestInvalidate(); } if (AfterPaste != null) { AfterPaste(this, new RangeEventArgs(this.selectionRange)); } } return(true); }
/// <summary> /// Copy data from Clipboard and put on grid. /// /// Currently ReoGrid supports the following types of source from the clipboard. /// - Data from another ReoGrid instance /// - Plain/Unicode Text from any Windows Applications /// - Tabbed Plain/Unicode Data from Excel or similar applications /// /// When data copied from another ReoGrid instance, and the destination range /// is bigger than the source, ReoGrid will try to repeat putting data to fill /// the destination range entirely. /// /// Todo: Copy border and cell style from Excel. /// </summary> public bool Paste() { if (IsEditing) { this.controlAdapter.EditControlPaste(); } else { // Paste method will always perform action to do paste // do nothing if in readonly mode if (this.HasSettings(WorksheetSettings.Edit_Readonly) // or selection is empty || this.selectionRange.IsEmpty) { return(false); } try { this.controlAdapter.ChangeCursor(CursorStyle.Busy); PartialGrid partialGrid = null; string clipboardText = null; #if WINFORM || WPF DataObject data = Clipboard.GetDataObject() as DataObject; if (data != null) { partialGrid = data.GetData(ClipBoardDataFormatIdentify) as PartialGrid; if (data.ContainsText()) { clipboardText = data.GetText(); } } #elif ANDROID #endif // WINFORM || WPF if (partialGrid != null) { #region Partial Grid Pasting int startRow = selectionRange.Row; int startCol = selectionRange.Col; int rows = partialGrid.Rows; int cols = partialGrid.Columns; int rowRepeat = 1; int colRepeat = 1; if (selectionRange.Rows % partialGrid.Rows == 0) { rows = selectionRange.Rows; rowRepeat = selectionRange.Rows / partialGrid.Rows; } if (selectionRange.Cols % partialGrid.Columns == 0) { cols = selectionRange.Cols; colRepeat = selectionRange.Cols / partialGrid.Columns; } var targetRange = new RangePosition(startRow, startCol, rows, cols); if (!RaiseBeforePasteEvent(targetRange)) { return(false); } if (targetRange.EndRow >= this.rows.Count || targetRange.EndCol >= this.cols.Count) { // TODO: paste range overflow // need to notify user-code to handle this return(false); } // check whether the range to be pasted contains readonly cell if (this.CheckRangeReadonly(targetRange)) { this.NotifyExceptionHappen(new OperationOnReadonlyCellException("specified range contains readonly cell")); return(false); } DoAction(new SetPartialGridAction(new RangePosition( startRow, startCol, rows, cols), partialGrid)); #endregion // Partial Grid Pasting } else if (!string.IsNullOrEmpty(clipboardText)) { #region Plain Text Pasting var arrayData = RGUtility.ParseTabbedString(clipboardText); int rows = Math.Max(selectionRange.Rows, arrayData.GetLength(0)); int cols = Math.Max(selectionRange.Cols, arrayData.GetLength(1)); var targetRange = new RangePosition(selectionRange.Row, selectionRange.Col, rows, cols); if (!RaiseBeforePasteEvent(targetRange)) { return(false); } if (this.controlAdapter != null) { var actionSupportedControl = this.controlAdapter.ControlInstance as IActionControl; if (actionSupportedControl != null) { actionSupportedControl.DoAction(this, new SetRangeDataAction(targetRange, arrayData)); } } #endregion // Plain Text Pasting } } catch (Exception ex) { // raise event to notify user-code there is error happened during paste operation //if (OnPasteError != null) //{ // OnPasteError(this, new RangeOperationErrorEventArgs(selectionRange, ex)); //} this.NotifyExceptionHappen(ex); } finally { this.controlAdapter.ChangeCursor(CursorStyle.Selection); RequestInvalidate(); } if (AfterPaste != null) { AfterPaste(this, new RangeEventArgs(this.selectionRange)); } } return(true); }