private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dataGridView.SelectedCells.Count == 1)
            {
                Clipboard.SetText(Convert.ToString(dataGridView.SelectedCells[0].Value));
                return;
            }

            var cells = dataGridView.SelectedCells.Cast <DataGridViewCell>();
            int xmin = cells.Min(cell => cell.ColumnIndex);
            int xmax = cells.Max(cell => cell.ColumnIndex);
            int ymin = cells.Min(cell => cell.RowIndex);
            int ymax = cells.Max(cell => cell.RowIndex);
            int w = xmax - xmin + 1, h = ymax - ymin + 1;

            if (w * h != dataGridView.SelectedCells.Count)
            {
                MessageBox.Show(
                    this,
                    "Cannot copy a non-rectangular cell selection to clipboard.",
                    null,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return;
            }

            var data = new object[h, w];

            for (int y = ymin; y <= ymax; ++y)
            {
                for (int x = xmin; x <= xmax; ++x)
                {
                    data[y - ymin, x - xmin] = dataGridView[x, y].Value;
                }
            }

            using (var stream = new MemoryStream())
                using (var writer = new StreamWriter(stream))
                {
                    CSV.Write(data, writer);
                    writer.Flush();

                    stream.Position = 0;
                    Clipboard.SetDataObject(new DataObject("Csv", stream), true);
                }
        }
        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dataGridView.SelectedCells.Count == 1 && Clipboard.ContainsText())
            {
                dataGridView.SelectedCells[0].Value = Clipboard.GetText();
                return;
            }

            if (!Clipboard.ContainsData("Csv"))
            {
                return;
            }

            var cells = dataGridView.SelectedCells.Cast <DataGridViewCell>();
            int xmin = cells.Min(cell => cell.ColumnIndex);
            int xmax = cells.Max(cell => cell.ColumnIndex);
            int ymin = cells.Min(cell => cell.RowIndex);
            int ymax = cells.Max(cell => cell.RowIndex);
            int w = xmax - xmin + 1, h = ymax - ymin + 1;

            if (w * h != dataGridView.SelectedCells.Count)
            {
                MessageBox.Show(
                    this,
                    "Cannot paste from clipboard into a non-rectangular cell selection.",
                    null,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return;
            }

            object[,] data;

            object rawData = Clipboard.GetData("Csv");

            using (var stream = rawData as Stream)
                using (var reader = (stream == null) ? (TextReader) new StringReader(rawData.ToString()) : new StreamReader(stream))
                {
                    data = CSV.Parse(reader);
                }

            if (data.GetLength(0) != h || data.GetLength(1) != w)
            {
                MessageBox.Show(
                    this,
                    string.Format(
                        "Cannot paste block of cells of size {0}x{1} from clipboard into cell selection of size {2}x{3}.",
                        data.GetLength(0), data.GetLength(1),
                        w, h),
                    null,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return;
            }

            int i = 0, j = 0;

            try
            {
                for (i = 0; i < h; ++i)
                {
                    for (j = 0; j < w; ++j)
                    {
                        Document.Data.Rows[ymin + i][xmin + j] = data[i, j];
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    this,
                    string.Format("Error while pasting cell at row {0}, column {1}: {2}", i, j, ex.Message),
                    null,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }