datagridview的若干問題與解決方案
datagridview做完已幾天了,是時候寫個總結了。
我的工作是datagridview讀取Excel資料,並能夠像操作Excel一樣進行複製、剪下、粘貼、清空、增加行、刪除行、增加列、刪除列,匯出Excel/Word.現將我遇到額問題與解決方案一一陳述。
1.匯入Excel。代碼走先。
public void ExcelToDataGridView(string filePath, DataGridView dataGridView1) { //根據路徑開啟一個Excel檔案並將資料填充到DataSet中 string strConn = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = " + filePath + "; Extended Properties = 'Excel 8.0;HDR =YES; IMEX=2'"; // 匯入時包含Excel中的第一行資料,並且將數字和字元混合的儲存格視為文本進行匯入 OleDbConnection conn = new OleDbConnection(strConn); conn.Open(); string strExcel = "select * from [sheet1$]"; OleDbDataAdapter myCommand = new OleDbDataAdapter(strExcel, strConn); ds = new DataSet(); myCommand.Fill(ds, "[Sheet1$]"); dataGridView1.DataMember = "[Sheet1$]"; dataGridView1.DataSource = ds; conn.Close(); dataGridView1.AllowUserToAddRows = true; //禁用自動排序 for (int k= 0;k < dataGridView1.Columns.Count; k++) { dataGridView1.Columns[k].SortMode = DataGridViewColumnSortMode.NotSortable; } int cCount = dataGridView1.ColumnCount; int rCount = dataGridView1.RowCount; double[,] array = new double[rCount, cCount]; for (int j = 0; j < rCount - 1; j++) // 逐行遍曆 { for (int i = 0; i < cCount - 1; i++) // 逐列遍曆 { array[j, i] = Convert.ToDouble(dataGridView1.Rows[j].Cells[i].Value.ToString()); } } }
private void button1_Click(object sender, EventArgs e) { // 開啟一個選擇框 OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Excel檔案"; ofd.FileName = ""; ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); ofd.Filter = "Excel檔案(*.xls)|*.xls"; ofd.ValidateNames = true; // 檔案有效性驗證vValidateNames,驗證使用者輸入的是否是一個有效windows 檔案名稱 ofd.CheckFileExists = true; // 驗證檔案的有效性 ofd.CheckPathExists = true; // 驗證路徑的有效性 strName = string.Empty; if (ofd.ShowDialog() == DialogResult.OK) { strName = ofd.FileName; } if (strName == "") { MessageBox.Show("沒有選擇Excel檔案!無法進行資料匯入"); return; } DgvSet EtG = new DgvSet(); EtG.ExcelToDataGridView(strName, this.dataGridView1); }
用此方法匯入Excel最為方便,注意需要命名空間using System.Data.OleDb;
2.我遇到最大的難題就是插入行,因為此匯入Excel方法會綁定資料來源,當你用代碼插入時總會提示“當控制項與資料來源綁定時,無法以編程方式向其中添加行”,最後得以高手協助,搞定。見代碼。
public void AddExcelToDataGridView(DataGridView dataGridView1, int index) { dataGridView1.DataBindings.Clear(); DataRow row = row = ds.Tables[0].NewRow(); ds.Tables[0].Rows.InsertAt(row, index); dataGridView1.DataSource = ds; dataGridView1.AllowUserToAddRows = true; }
//datagridview右鍵功能 private void 插入行ToolStripMenuItem_Click(object sender, EventArgs e) { try { //MessageBox.Show(dataGridView1.CurrentRow.Index.ToString()); DgvSet EtG = new DgvSet(); EtG.AddExcelToDataGridView( this.dataGridView1, dataGridView1.CurrentRow.Index); //this.dataGridView1.Rows.Insert(dataGridView1.CurrentRow.Index, 1); //this.dataGridView1.Rows.Insert(dataGridView1.CurrentRow.Index, new DataGridViewRow()); } catch (Exception ex) { MessageBox.Show(ex.Message.ToString()); } }
3.就是datagridview儲存格為空白問題,而datagridview儲存格為空白不能使用NULL,應使用DBNull.Value;如下:
public void Clear(DataGridView dataGridView1) { foreach (DataGridViewCell cell in dataGridView1.SelectedCells) { cell.Value = DBNull.Value; } }
4.另一個較複雜問題就是粘貼,,粘貼不僅要能夠從外面的Excel複製在datagridview粘貼,本身datagridview還要能夠複製粘貼,而且,當複製行列數超過datagridview總行列數時,datagridview還要能夠自動增加行與列。代碼
#region 粘貼 public int Paste(DataGridView dgv, string pasteText, int kind, bool b_cut) { try { if (kind == 0) { pasteText = Clipboard.GetText(); } if (string.IsNullOrEmpty(pasteText)) return -1; int rowNum = 0; int columnNum = 0; //獲得當前剪貼簿內容的行、列數 for (int i = 0; i < pasteText.Length; i++) { if (pasteText.Substring(i, 1) == "\t") { columnNum++; } if (pasteText.Substring(i, 1) == "\n") { rowNum++; } } Object[,] data; //粘貼板上的資料來自於EXCEL時,每行末都有\n,在DATAGRIDVIEW內複製時,最後一行末沒有\n if (pasteText.Substring(pasteText.Length - 1, 1) == "\n") { rowNum = rowNum - 1; } columnNum = columnNum / (rowNum + 1); data = new object[rowNum + 1, columnNum + 1]; String rowStr; //對數組賦值 for (int i = 0; i < (rowNum + 1); i++) { for (int colIndex = 0; colIndex < (columnNum + 1); colIndex++) { rowStr = null; //一行中的最後一列 if (colIndex == columnNum && pasteText.IndexOf("\r") != -1) { rowStr = pasteText.Substring(0, pasteText.IndexOf("\r")); } //最後一行的最後一列 if (colIndex == columnNum && pasteText.IndexOf("\r") == -1) { rowStr = pasteText.Substring(0); } //其他行列 if (colIndex != columnNum) { rowStr = pasteText.Substring(0, pasteText.IndexOf("\t")); pasteText = pasteText.Substring(pasteText.IndexOf("\t") + 1); } if (rowStr == string.Empty) rowStr = null; data[i, colIndex] = rowStr; } //截取下一行資料 pasteText = pasteText.Substring(pasteText.IndexOf("\n") + 1); } /*檢測值是否是列頭*/ /* //擷取當前選中儲存格所在的列序號 int columnindex = dgv.CurrentRow.Cells.IndexOf(dgv.CurrentCell); //擷取擷取當前選中儲存格所在的行序號 int rowindex = dgv.CurrentRow.Index;*/ int columnindex = -1, rowindex = -1; int columnindextmp = -1, rowindextmp = -1; if (dgv.SelectedCells.Count != 0) { columnindextmp = dgv.SelectedCells[0].ColumnIndex; rowindextmp = dgv.SelectedCells[0].RowIndex; } //取到最左上方的 儲存格編號 foreach (DataGridViewCell cell in dgv.SelectedCells) { //dgv.Rows[cell.RowIndex].Selected = true; columnindex = cell.ColumnIndex; if (columnindex > columnindextmp) { //交換 columnindex = columnindextmp; } else columnindextmp = columnindex; rowindex = cell.RowIndex; if (rowindex > rowindextmp) { rowindex = rowindextmp; rowindextmp = rowindex; } else rowindextmp = rowindex; } if (kind == -1) { columnindex = 0; rowindex = 0; } //如果行數超過當前列表行數 if (rowindex + rowNum + 1 > dgv.RowCount) { int mm = rowNum + rowindex + 1 - dgv.RowCount; for (int ii = 0; ii < mm+1; ii++) { dgv.DataBindings.Clear(); DataRow row = row = ds.Tables[0].NewRow(); ds.Tables[0].Rows.InsertAt(row, ii + rowindex + 1); } } //如果列數超過當前列表列數 if (columnindex + columnNum + 1 > dgv.ColumnCount) { int mmm = columnNum + columnindex + 1 - dgv.ColumnCount; for (int iii= 0; iii < mmm; iii++) { dgv.DataBindings.Clear(); DataGridViewTextBoxColumn colum = new DataGridViewTextBoxColumn(); dgv.Columns.Insert(columnindex+1, colum); } } //增加超過的行列 for (int j = 0; j < (rowNum + 1); j++) { for (int colIndex = 0; colIndex < (columnNum + 1); colIndex++) { if (colIndex + columnindex < dgv.Columns.Count) { if (dgv.Columns[colIndex + columnindex].CellType.Name == "DataGridViewTextBoxCell") { if (dgv.Rows[j + rowindex].Cells[colIndex + columnindex].ReadOnly == false) { dgv.Rows[j + rowindex].Cells[colIndex + columnindex].Value = data[j, colIndex]; dgv.Rows[j + rowindex].Cells[colIndex + columnindex].Selected = true; } } } } } //清空剪下板內容 if (b_cut) Clipboard.Clear(); return 1; } catch { return -1; } } #endregion
5.另外,因為datagridview無法編輯第一列,當插入列時,就無法在datagridview上編輯,只能增加列時就自動傳一個列名,我是這樣做的:
private void 插入列ToolStripMenuItem_Click(object sender, EventArgs e) { try { DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn(); int columnindex = dataGridView1.CurrentRow.Cells.IndexOf(dataGridView1.CurrentCell); string newName = "New" + (k++); column.HeaderText =newName; //column.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; //column.CellTemplate.Style.BackColor = Color.Beige; dataGridView1.Columns.Insert(columnindex + 1, column); } catch(Exception error) { MessageBox.Show(error.Message); } }
6.其他的代碼就不一一上傳了,只把主要的問題和代碼上傳,有需要的郵件給我,我傳給你。
第一次發這麼長的,求人品。。。。。。。。
(附圖,有圖有真相,見下):