public List <SpreadsheetCellData> AddColumn(int?col = null, List <SpreadsheetCellData> restoreCells = null, SpreadsheetColumnData restoreColumn = null)
        {
            int colIndex = col.HasValue ? col.Value : columnDatas.Count;

            if (colIndex > 0 && colIndex < columnDatas.Count)
            {
                // check for dataTable. Cannot insert between dataTable, so only the first column of dataTable can be inserted
                for (int row = 0; row < rowDatas.Count; ++row)
                {
                    SpreadsheetCellData cell = cells[row][colIndex];
                    if (cell.dataTableData != null)
                    {
                        SpreadsheetRangeData rangeData = valueStore.CreateSpreadsheetRangeDataFromRangeId(cell.dataTableData.rangeId);
                        PointInt?            position  = rangeData.GetPositionOfCell(cell);
                        if (position.Value.X > 0)
                        {
                            throw new Exception("Cannot change part of a data table");
                        }
                    }
                }
            }

            if (restoreColumn == null)
            {
                string newColumnId = columnIdGenerator.NewVariableName();
                columnDatas.Insert(colIndex, new SpreadsheetColumnData(valueStore)
                {
                    id = GetColumnId(newColumnId)
                });
            }
            else
            {
                columnDatas.Insert(colIndex, restoreColumn);
            }

            if (restoreCells == null)
            {
                List <SpreadsheetCellData> newColumn = new List <SpreadsheetCellData>();
                for (int row = 0; row < rowDatas.Count; ++row)
                {
                    string expression            = ResolveRowExpressionForColumn(rowDatas[row].expression, colIndex);
                    SpreadsheetCellData cellData = new SpreadsheetCellData(this.valueStore, GetCellId(row, colIndex), expression);
                    cells[row].Insert(colIndex, cellData);
                    newColumn.Add(cellData);
                }
                return(newColumn);
            }
            else
            {
                for (int row = 0; row < rowDatas.Count; ++row)
                {
                    cells[row].Insert(colIndex, restoreCells[row]);
                }
                return(restoreCells);
            }
        }
        public List <SpreadsheetCellData> AddRow(int?row = null, List <SpreadsheetCellData> restoreCells = null, SpreadsheetRowData restoreRow = null)
        {
            int rowIndex = row.HasValue ? row.Value : rowDatas.Count;

            if (rowIndex > 0 && rowIndex < rowDatas.Count)
            {
                // check for dataTable. Cannot insert between dataTable, so only the first row of dataTable can be inserted
                foreach (SpreadsheetCellData cell in cells[rowIndex])
                {
                    if (cell.dataTableData != null)
                    {
                        SpreadsheetRangeData rangeData = valueStore.CreateSpreadsheetRangeDataFromRangeId(cell.dataTableData.rangeId);
                        PointInt?            position  = rangeData.GetPositionOfCell(cell);
                        if (position.Value.Y > 0)
                        {
                            throw new Exception("Cannot change part of a data table");
                        }
                    }
                }
            }

            if (restoreRow == null)
            {
                string newRowId = rowIdGenerator.NewVariableName();
                //rowIds.Insert(rowIndex, newRowId);
                rowDatas.Insert(rowIndex, new SpreadsheetRowData(valueStore)
                {
                    id = GetRowId(newRowId)
                });
            }
            else
            {
                rowDatas.Insert(rowIndex, restoreRow);
            }

            if (restoreCells == null)
            {
                List <SpreadsheetCellData> newRow = new List <SpreadsheetCellData>();
                for (int col = 0; col < columnDatas.Count; ++col)
                {
                    string expression = ResolveColumnExpressionForRow(columnDatas[col].expression, rowIndex);
                    newRow.Add(new SpreadsheetCellData(this.valueStore, GetCellId(rowIndex, col), expression));
                }
                cells.Insert(rowIndex, newRow);
                return(newRow);
            }
            else
            {
                cells.Insert(rowIndex, restoreCells);
                return(restoreCells);
            }
        }