excel中如何动态地创建控件以显示查询结果_Excel催化剂开源第23波-VSTO开发辅助录入功能...
在Excel催化劑的幾大輔助錄入功能中(數(shù)據(jù)驗證保護、數(shù)據(jù)多級聯(lián)動輸入、關鍵詞模糊智能匹配輸入)中,用了一些customxmlPart技術來存儲配置信息,同時在關鍵詞模糊智能匹配輸入中,用了一個VSTO開發(fā)才能滿足的自定義控件技術,很值得啟發(fā),拿出來給大家作一分享。
一般來說控件都是放到窗體或任務窗格中,但Excel同樣支持將控件放到工作表單元格上,如前面提到的picturebox容器,放到單元格區(qū)域上,然后在容器上發(fā)圖片,實現(xiàn)插入圖片功能,同樣地也可以存放單選、復選這些控件,當然,嚴格來說,在VBA環(huán)境下也可以完成這些工作。
在VSTO框架下,有一革命性的突破是,可以放我們的自定義控件,這個具體和VBA的自定義Active控件有什么不一樣,就不太知道,但起碼VSTO放自定義控件,開發(fā)成本極低。
自定義控件,可直接用到工作表單元格中
具體實現(xiàn)原理
通過用戶配置操作,將需要進行快速錄入的區(qū)域記錄下來,用SelectionChange事件來響應,若用戶選擇到這些單元格時,就激發(fā)事件方法,顯示自定義控件,并讓光標定位到自定義控件的查找控件TextBox等待用戶輸入。輸入過程中動態(tài)控制下方DataGridView的查找結果,用戶可以按方向箭下上在結果中選擇對應的條目,再按Enter或Tab鍵確定內(nèi)容錄入。
具體代碼
先綁定事件
internal void ExcelApp_SheetSelectionChangeFastInput(object Sh, Excel.Range Target) { try { Globals.ThisAddIn.Application.SheetSelectionChange -= this.ExcelApp_SheetSelectionChangeFastInput; FormFastInput.UscFastInput.UserControlTextBox.KeyDown -= FormFastInput.UscFastInput.textBox1_KeyDown; if (Target.Cells.CountLarge == 1) { FormFastInput.SelectionChangeOfFastInput(Target); } } catch (Exception ex) { Common.OutMsgError(ex); } finally { Globals.ThisAddIn.Application.SheetSelectionChange += this.ExcelApp_SheetSelectionChangeFastInput; FormFastInput.UscFastInput.UserControlTextBox.KeyDown += FormFastInput.UscFastInput.textBox1_KeyDown; } }響應錄入單元格區(qū)域的代碼,將自定義控件顯示尺寸變大,之前有個關鍵點是隱藏了自定義控件后再顯示,焦點不能順利落到自定義控件的搜索TextBox上,采用了迂回的隱藏時不是真隱藏,只是縮小成1*1像素大小,好像后來其他位置發(fā)現(xiàn)了更好解決方案,原代碼沒有來得及重新改過來。
public static void SelectionChangeOfFastInput(Excel.Range Target) { FormFastInput.CurrentSelectCell = Target; int fastInputID = GetFastInputID(Target);//找不到有交集時返回int最大值 if (fastInputID < int.MaxValue) { FormFastInput.UscFastInput.FastInputID = fastInputID;//傳入usc中,下一次textbox事件可以直接用,不用再找。 ShowUscAndSettingUscFastInputTextBox(Target); FormFastInput.UscFastInput.IsTextChanged = false; FormFastInput.UscFastInput.DgvSelectedRowIndex = 0; FormFastInput.UscFastInput.IsFirstEnterDgv = true;//為了能夠在首次為0時仍然是0而不是+1的效果 SettingUscLableAndFilterDgv(fastInputID); } else { //FormFastInput.InputUserControl.Visible = false; FormFastInput.InputUserControl.Width = 1; //縮小成1而不是隱藏,為了下次激活時可以順利進入textbox激活 FormFastInput.InputUserControl.Height = 1; } }有個小細節(jié),在窗體中,怎樣控制默認的Enter和Tab鍵的功能,默認為窗體退出鍵和TabIndex跳轉(zhuǎn)鍵,這里有個對一個方法進行重寫即可。
protected override bool ProcessDialogKey(Keys keyData) { if (keyData == Keys.Enter || keyData == Keys.Tab) { ReturnValueFromUserControl(keyData); return true; } return base.ProcessDialogKey(keyData); }改變其默認功能后,就可以像其他鍵一樣捕捉其KeyDown事件,例如此處的錄入功能中,按Enter是跳轉(zhuǎn)到下一行,按Tab是跳轉(zhuǎn)到右側(cè)列,實現(xiàn)鍵盤盲打錄入不依賴鼠標實現(xiàn)。
internal void textBox1_KeyDown(object sender, KeyEventArgs e) { try { if (this.IsTextChanged) { switch (e.KeyCode) { case Keys.Down: if (this.IsFirstEnterDgv == true || this.DgvSelectedRowIndex == this.dataGridView1.Rows.Count - 1) { this.DgvSelectedRowIndex = 0; this.IsFirstEnterDgv = false; } else { this.DgvSelectedRowIndex++; } RedirectDgvRow(); break; case Keys.Up: if (this.DgvSelectedRowIndex == 0) { this.DgvSelectedRowIndex = this.dataGridView1.Rows.Count - 1; } else { this.DgvSelectedRowIndex--; } RedirectDgvRow(); break; case Keys.Tab: ReturnValueFromUserControl(Keys.Tab); break; case Keys.Enter: ReturnValueFromUserControl(Keys.Enter); break; default: break; } } else//剛剛進到文本框中,想跳出來選擇其他單元格時 { switch (e.KeyCode) { case Keys.Down: case Keys.Enter: FormFastInput.CurrentSelectCell.Offset[1, 0].Select(); break; case Keys.Up: FormFastInput.CurrentSelectCell.Offset[-1, 0].Select(); break; case Keys.Left: FormFastInput.CurrentSelectCell.Offset[0, -1].Select(); break; case Keys.Right: case Keys.Tab: FormFastInput.CurrentSelectCell.Offset[0, 1].Select(); break; } } } catch (Exception) { } finally { } } private void ReturnValueFromUserControl(Keys keys) { bool isDgvSelected = this.dataGridView1.Rows.Cast().Any(s => s.Selected); //當dgv有選擇列時 if (isDgvSelected) { FormFastInput.CurrentSelectCell.Value2 = this.dataGridView1.SelectedRows[0].Cells[FormFastInput.ReturnColIndex].Value; } else { FormFastInput.CurrentSelectCell.Value2 = this.textBox1.Text; } if (keys == Keys.Tab) { FormFastInput.CurrentSelectCell.Offset[0, 1].Select(); } else if (keys == Keys.Enter) { FormFastInput.CurrentSelectCell.Offset[1, 0].Select(); } }結語
在VSTO框架下,有大量微軟工程師為我們搭建好的底層技術,使我們在上層構建業(yè)務代碼時變得如此輕松,此篇給大家展示了在工作表單元格區(qū)域上創(chuàng)建自定義控件的能力,發(fā)揮得當,較直接彈出窗體的效果要友好得多。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的excel中如何动态地创建控件以显示查询结果_Excel催化剂开源第23波-VSTO开发辅助录入功能...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: loop转移指令
- 下一篇: 转移的目的地址在指令中的jmp指令 转