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