1. 程式人生 > >實現Excelvba測試軟體中工作表使用者按鈕的執行限定

實現Excelvba測試軟體中工作表使用者按鈕的執行限定

1  引言
作為一個優秀的表格處理軟體和系統開發平臺,Excel擁有許多無可替代的優勢。基於Excel環境開發的管理資訊系統,具有操作直觀性強、開發週期短的特點,因此形成了熟悉Excel操作的廣大使用者。為了保證開發系統的正常渠道流通及著作者利益,必須保護系統的使用許可權,本文通過VBA的開發應用,提出了一種Excel工作表使用者按鈕的限定方法,以此來完善其系統測試軟體的功能。
2  限定按鈕執行及其對應過程程式碼
限定工作表使用者按鈕的執行包括兩個方面的含義,即限定其按鈕物件的顯示及其指定巨集過程程式碼的有效性,兩者結合在一起加以實現,才能起到既展現軟體功能,又真正限制其過分執行操作的作用,從而體現對使用者軟體的測試目的。
2.1 查詢按鈕執行過程程式碼
限定按鈕物件及其執行程式碼,首要的問題便是獲得其對應的執行程式碼過程名,並在當前工程的所有程式碼模組中查詢其程式碼位置。
實踐表明,按鈕物件與圖形影象和藝術字體一樣,都屬於Shape形狀物件,它們都有其對應的OnAction屬性,代表其被指定的巨集過程程式碼名稱。需要指出的是窗體型別按鈕對應的巨集過程程式碼一般位於工程的標準模組中,而ActiveX按鈕過程程式碼則位於工作表程式碼模組中,且其對應的正確執行過程名為其按鈕名與相應的事件名的連線串。為了查詢某個按鈕對應的過程程式碼,需要對VBE(Visual Basic 編輯器)的下層物件VBComponents進行搜尋。VBComponents物件代表VBE編輯器下的各個程式碼模組VBComponent。通過對某一VBComponent的下一層物件CodeModule的相關屬性的訪問,可以獲得諸如模組程式碼總行數等資訊,也可以通過其Find方法查詢指定內容的程式碼行。下面即為查詢按鈕過程、處理按鈕過程程式碼的演算法程式碼。
SheetsCount = ActiveWorkbook.Worksheets.Count
'對所有工作表中的所有按鈕物件迴圈
For i = 1 To SheetsCount
 Set MySheet = Worksheets(i)
 MySheet.Activate
 For Each sh In MySheet.Shapes
  sh.Visible = True
  sh.Select
  '取得選定物件所對應的過程名
  MyProname = sh.OnAction
  '對於ActiveX按鈕,則只取得其onClick事件過程名
  If sh.Type = msoOLEControlObject Then
    MyProname = sh.Name & "_Click"
  End If
  ……
  ' StartLine、StartCol為設定查詢按鈕過程名的開始行、列序號,並在程式碼查詢成功時' 返回所在的程式碼行、列序號
  StartLine = 1
  StartCol = 1
  Set MyCoponent = Application.VBE.ActiveVBProject.VBComponents
  '在各程式碼模組中查詢按鈕過程
  For Each ch In MyCoponent
    If sh.Type = msoOLEControlObject And ch.Name <> sh.Parent.CodeName Then
      GoTo Label4
  End If
'本程式碼模組的程式碼總行數
    LinesCount = ch.CodeModule.CountOfLines
    Endline = LinesCount
    '忽略註釋行,查詢正確的過程頭部位置
    Do While ch.CodeModule.Find("Sub " & MyProname & "()", StartLine, StartCol, Endline, 1, False, False) And Left(Trim(ch.CodeModule.Lines(StartLine, 1)), 1) = "'"
        StartLine = StartLine + 1
        StartCol = 1
        Endline = LinesCount
    Loop
    '找到了過程頭部位置
    If ch.CodeModule.Find("Sub " & MyProname & "()", StartLine, StartCol, LinesCount, 1, False, False) And ch.CodeModule.ProcOfLine(StartLine, vbext_pk_Proc) = MyProname Then
    '若還沒有插入規定的程式碼
    If Trim(ch.CodeModule.Lines(StartLine + 1, 1)) <> "'隱藏過程程式碼" Then
    '程式碼1……,在按鈕過程程式碼的首部加入過程呼叫程式碼
    '程式碼2……,調整本程式碼行以後的已經插入的程式碼行呼叫引數
    Endif
   End If
Label4:
Next
Next
Next i
ActiveWorkbook.Save
2.2 插入過程呼叫程式碼
經過查詢按鈕的執行過程程式碼的正確位置,就能夠限定其執行的有效性。本文的處理方法是,在按鈕的對應過程程式碼的首部加入兩行程式碼,如:
'隱藏過程程式碼
Call 模組5.隱藏過程程式碼(256,73,”Sheet2”,2,3)
可以看出第一行程式碼是一註釋行,第二行程式碼是一過程呼叫。正是這一過程呼叫,在按鈕點選時首先被執行,從而實現了對按鈕執行的準確計數,並在按鈕執行到達規定次數時,阻止其執行。
下面的程式碼通過對找到的按鈕過程所在程式碼模組VBComponent的下層物件CodeModule採用InsertLines方法,首先在按鈕對應過程的首部插入兩行臨時程式碼,然後通過該物件的ReplaceLine方法,將它們分別替換為正確的上述兩行程式碼。這樣先插入程式碼行、後替換程式碼行的目的是,在插入程式碼行後便於獲得準確的過程起始程式碼行號,從而為下面的替換程式碼行語句準備正確的引數。下面即是上述查詢按鈕過程程式碼中“程式碼1”位置處的演算法程式碼,其功能是在查詢到的按鈕過程程式碼的首部加入上述的兩行程式碼:
ModuleName = Application.VBE.SelectedVBComponent.Nam' 獲得過程所處的程式碼模組名
  CodeName = ch.Name
  ' 插入兩行臨時程式碼行
  ch.CodeModule.InsertLines StartLine + 1, "'插入程式碼行1"
  ch.CodeModule.InsertLines StartLine + 2, "'插入程式碼行2"
  ' 獲得模組程式碼總行數、過程起始行號、過程程式碼總行數
  LinesCount = ch.CodeModule.CountOfLines
' 過程程式碼起始行號
  ProcStartline = ch.CodeModule.ProcStartline(MyProname, vbext_pk_Proc)
' 過程程式碼總行數
  ProcCountLines = ch.CodeModule.ProcCountLines(MyProname, vbext_pk_Proc)
' 替換為兩行正確的程式碼行
  ch.CodeModule.ReplaceLine StartLine + 1, "'隱藏過程程式碼"
  ch.CodeModule.ReplaceLine StartLine + 2, "Call " & ModuleName & ".隱藏過程程式碼(" & ProcStartline & "," & ProcCountLines & "," & """" & CodeName & """" & "," & i & "," & sh.ZOrderPosition & ")"
此外,當按鈕被點選執行並進入到插入的呼叫過程內部時,還需要確定哪個按鈕被執行、執行的次數情況、以及執行按鈕的對應過程程式碼的行範圍等情況,以便準確地實施對執行按鈕及其過程程式碼的控制,所以在上述為按鈕過程替換為正確的過程呼叫程式碼的同時,需要添入正確的下列五個過程呼叫引數:
(1)按鈕的對應過程頭部所在程式碼模組中的程式碼起始行號;
(2)按鈕過程的對應程式碼行數;
(3)按鈕過程所處的程式碼模組名;
(4)按鈕所在的工作表序號;
(5)按鈕在所在工作表上的Shape形狀物件集合的序號。
從上面的插入程式碼中可以看出獲得這些引數的方法。針對上例的過程呼叫語句:Call 模組5.隱藏過程程式碼(256,73,”Sheet2”,2,3),其引數含義是:當第2個工作表中的第3個Shape物件(按鈕)執行次數到達規定次數時,則將名稱為“Sheet2”的程式碼模組中從256行起的73行程式碼設為無效,並將該按鈕進行隱藏。
值得注意的是,由於某些按鈕的對應過程程式碼加入了上述的過程呼叫程式碼,必然導致與之處於同一程式碼模組的其他按鈕過程、並已經添入的上述過程呼叫程式碼中的引數值出現偏差,因此需要對其中的過程程式碼起始行引數值作修改。下面的程式碼就是起這個作用,此程式碼須插入於前述查詢按鈕過程程式碼的“程式碼2”位置。
' 調整程式碼查詢起始位置
 Line1 = StartLine + 3
 Col1 = 1
 Endline = LinesCount
 Do
  If Not ch.CodeModule.Find("'隱藏過程程式碼", Line1, Col1, Endline, 1, False, False) Then
       Exit Do
  End If
' 如果查詢的程式碼不符合插入的程式碼格式,則繼續查詢
  If Col1 > 1 Then
     GoTo Label3
  End If
' 調整程式碼呼叫引數
  Str1 = ch.CodeModule.Lines(Line1 + 1, 1)
  If InStr(Str1, "Call") Then
   Str2 = Mid(Str1, InStr(Str1, "(") + 1, InStr(Str1, ",") - InStr(Str1, "(") + 1)
   Str2 = Trim(Str(Val(Trim(Str2)) + 2))
   Str1 = Left(Str1, InStr(Str1, "(")) & Str2 & Mid(Str1, InStr(Str1, ","))
   ch.CodeModule.ReplaceLine Line1 + 1, Str1
  End If
Label3:
  Line1 = Line1 + 1
  Col1 = 1
  Endline = LinesCount
 Loop
2.3 限定按鈕物件及其執行過程程式碼
限定按鈕物件本身,之前我們可以為之新增一個名為“按鈕執行次數記錄表”的工作表,以便使用其第i行j列的單元格來記錄當前工程第i個工作表上第j個形狀物件的執行次數。此外,為了實現對按鈕執行的準確計數,也需要在工程開啟時清除其內容,為了防止工作表資料意外修改,最好將其隱藏。這些均可以通過建立自動巨集來加以實現。
下面的程式碼即是按鈕執行時首先被呼叫的過程,其作用為對按鈕執行進行計數,在按鈕執行到達規定次數(這裡暫定為5次)時,隱藏該按鈕,並將其執行過程程式碼設為無效。這裡將程式碼行設為無效的方式是將其改成註釋,方法仍然是通過訪問指定的VBComponent下CodeModule物件的Lines屬性,並採用ReplaceLine方法來實現。改成的註釋行的格式為:'隱藏行*:原始碼行,其中*號代表其在本程式碼模組中的行號。下面的程式碼需要與前述的查詢按鈕過程程式碼位於同一程式碼模組。
Public Sub 隱藏過程程式碼(ByVal Beginline As Integer, ByVal LinesCount As Integer, ByVal CodeName As String, ByVal SheetIndex As Integer, ByVal ButtonIndex As Long)
……
      Sheets("按鈕執行次數記錄表").Cells(SheetIndex, ButtonIndex).Value = Sheets("按鈕執行次數記錄表").Cells(SheetIndex, ButtonIndex).Value + 1
      If Sheets("按鈕執行次數記錄表").Cells(SheetIndex, ButtonIndex).Value >= 5 Then
        Set MyCoponent = Application.VBE.ActiveVBProject.VBComponents
        For Each ch In MyCoponent
          If ch.Name <> CodeName Then
            GoTo Label5
          End If
          '將引數規定範圍的程式碼改為註釋
For k = Beginline To Beginline + LinesCount - 1
            Str1 = ch.CodeModule.Lines(k, 1)
            Str1 = "'隱藏行" & k - Beginline + 1 & ":" & Str1
            ch.CodeModule.ReplaceLine k, Str1
          Next k
          '隱藏執行的按鈕
          ActiveWorkbook.Sheets(SheetIndex).Shapes(ButtonIndex).Visible = False
Label5:
        Next
……
      End If
End Sub

3  支撐物件與軟體恢復
提供對VBE及其下層物件的訪問,需要建立對其支撐物件的引用,方法是進入VBE編輯環境,單擊“工具”選單的“引用”命令,然後加入對“Microsoft Visual Basic for Application Extensibility 5.3”的引用。
此外,軟體執行不應該影響其本來面目,所以在其被開啟時需要將其本身提供的介面恢復初態,在工程儲存時將已經變為註釋行的程式碼恢復原狀,下面通過編寫當前工程的自動巨集AUTO_OPEN和“ThisWorkbook”模組的Workbook_BeforeSave事件過程去分別實現這兩個軟體恢復功能:
Public Sub AUTO_OPEN()
'查詢輔助工作表
 SheetsCount = Application.ActiveWorkbook.Worksheets.Count
 For i = 1 To SheetsCount
   If ActiveWorkbook.Sheets(i).Name = "按鈕執行次數記錄表" Then
      FoundSheet = True
   End If
 Next i
 '新增或清除輔助工作表內容
 If Not FoundSheet Then
   ActiveWorkbook.Unprotect
   Worksheets.add.Move After:=Worksheets(SheetsCount)
   ActiveSheet.Name = "按鈕執行次數記錄表"
   ActiveSheet.Visible = False
 Else
   Sheets("按鈕執行次數記錄表").Cells.Clear
   Sheets("按鈕執行次數記錄表").Visible = False
 End If
 '將工作表中按鈕恢復為顯示狀態
 SheetsCount = ActiveWorkbook.Worksheets.Count
 For i = 1 To SheetsCount
   Set MySheet = Worksheets(i)
   For Each sh In MySheet.Shapes
    If sh.Visible = False Then sh.Visible = True
   Next
 Next i
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'恢復註釋行為原來的正式程式碼行
 Set MyCoponent = Application.VBE.ActiveVBProject.VBComponents
  For Each ch In MyCoponent
    StartLine = 1
    StartCol = 1
    LinesCount = ch.CodeModule.CountOfLines
    Endline = LinesCount
    Do While ch.CodeModule.Find("'隱藏行", StartLine, StartCol, Endline, 1, False, False)
      If StartCol <> 1 Then GoTo Label7
      Str1 = ch.CodeModule.Lines(StartLine, 1)
      Str1 = Mid(Str1, InStr(Str1, ":") + 1)
      ch.CodeModule.ReplaceLine StartLine, Str1
Label7:
      StartLine = StartLine + 1
      StartCol = 1
      Endline = LinesCount
    Loop
  Next
End Sub

4  結束語
綜上所述,針對基於Excel VBA測試軟體的使用許可權設定,本文提出的通過執行過程程式碼的控制方法實現工作表使用者按鈕的限定技術,操作起來儘管存在一定的麻煩,但仍然具有相當的實用性。

相關推薦

實現Excelvba測試軟體工作使用者按鈕執行限定

1  引言作為一個優秀的表格處理軟體和系統開發平臺,Excel擁有許多無可替代的優勢。基於Excel環境開發的管理資訊系統,具有操作直觀性強、開發週期短的特點,因此形成了熟悉Excel操作的廣大使用者。為了保證開發系統的正常渠道流通及著作者利益,必須保護系統的使用許可權,本文

Java實現測試結果寫入Excel

自動化測試指令碼執行完以後,會有一個測試結果,無論是通過框架還是Jenkins平臺生成的結果,可讀性都不是太好,為了方便手工測試人員檢視結果,測試完成後把結果寫入Excel是一個不錯的方法,但是指令碼多了,通過人工來寫,無疑加重了自動化測試人員的工作,為了解決這個問題,我

在 Excel 以程式設計方式複製工作會導致執行時錯誤 1004

建立一個新的工作簿,然後保留一個工作表並刪除其他所有工作表。設定該工作簿的格式,然後新增模板必須預設包含的所有文字、資料和圖表。單擊“Microsoft Office 按鈕”,然後單擊“另存為”。在“檔名”框中,鍵入所需的 Excel 模板名稱。在“儲存型別”列表中,單擊“模板 (*.xltx)”,然後單擊“

C#實現對SQL資料庫的查詢、新增、修改、刪除資料

經常用到的物件有:SqlConnection,SqlAdapter,SqlCommand、Dataset、DataGrid和DataReader等,以SqlConnection,SqlAdapter,SqlCommand、Dataset、DataGrid物件,操作SQL的例

VBA -- 實現按指定條件拆分工作的功能

大資料背景下,資料變成了巨大的財富。各種資料庫如關係型資料庫SQL/Oracle和非關係型資料庫MangoDB/Redis等的演化和應用更加豐富;同時資料分析從資料採集、資料預處理到資料整合、資料探勘的需求也更大。從資料採集到資料探勘,最終服務企業運營,是一條完整和嚴謹的資料

BootStrap-CSS樣式_佈局元件_導航欄的(按鈕文字連結對齊方式)

導航欄中的表單 使 用 .navbar-form class。這確保了表單適當的垂直對齊和在較窄的視口中摺疊的行為。使用對齊方 式選項來決定導航欄中的內容放置在哪裡。 導航欄中的按鈕 使用 class .navbar-btn 向不在 <form> 中的 <button&

解決Windows XP工作列不顯示執行程式按鈕的故障

    故障現象:程式在執行,但是工作列卻不顯示相應的按鈕,導致多個程式同時執行時,無法從工作列迅速切換,只能用 Alt+TAB 鍵切換,既慢又不直觀,還經常錯誤切換到其他程式。   解決過程:一直不太敢用網上所謂修改、強化工作列的軟體,怕有垃圾程式碼/病毒/後門/木馬/惡意

pl/sql developer 匯出資料庫到可執行的.sql 指令碼檔案

PL/SQL自帶匯出資料庫中表到.sql指令碼檔案的工具。 1.在objects視窗中,選中表》右擊》Export Data 2.選》SQL Inserts 選擇:Create tables,其他選項看情況選擇。 3.Output file:選擇輸出路徑及檔名。 4

我在華為,軟體測試人員在工作如何運用Linux?

從事過軟體測試的小夥們就會明白會使用Linux是多麼重要的一件事,工作時需要用到,面試時會被問到,簡歷中需要寫到。對於軟體測試人員來說,不需要你多麼熟練使用Linux所有命令,也不需要你對Linux系統完全瞭解,你只需要學會一些常用的基本命令,這些命令足夠支撐你去檢視日誌,定位bug,修改檔案,搭建環境就

Excel2010工作如何導入txt文件

tac img 對話 如何 txt文件 exc 分享 導入txt bsp 1、打開Excel2010,點擊“數據”選項卡,然後在最左邊的“獲取外部數據”菜單中選擇“自文本”選項,在“導入文本文件”窗口中選擇需要導入的文件。如圖: 2、打開“文本導入向導-步驟之1(共3步)

[VBA]匯總多個工作簿的指定工作到同一個工作簿的指定工作

速度慢 excel trre books for each loop 表格 columns ive sub 匯總多個工作簿() Application.ScreenUpdating = False Dim wb As Workbook, f As String, l As

VBS讀取txt文檔數據查找Excel單元格數據符合條件的剪切到工作2

msg readline style 新建 font cti pre creat ins Dim fso,f,a set oExcel = CreateObject( "Excel.Application" ) oExcel.Visible = false ‘

html提交單並實現不跳轉頁面處理返回值

html value put 提示 pan sdn type detail all <html> <head> <script type="text/javascript" src="h

Winform開發框架工作流模塊的設計分析

展示 隨筆 還需 應用 廣泛 其中 撤銷 適合 根據 在較早博客隨筆裏面寫過文章《Winform開發框架之簡易工作流設計》之後,很久沒有對工作流部分進行詳細的介紹了,本篇繼續這個主題,詳細介紹其中的設計、實現及效果給大家,這個工作流在好幾年前就應用在了市行業審批系統上,經過

VUE關於單提交的簡單實現

eat style OS 關於 select city ole temp console main.js import Vue from "../vue.js"; import App from "./App.js"; //啟動 new Vue({ el:"#ap

模板方法模式 + 觀察模式 + 簡單工廠模式 + 單例模式實現一個簡單的數據讀寫

private 數據庫鏈 obs imp 通知 model 數據表 ring pri 實現功能: 對數據表的讀要緩存起來,對數據表的寫需要清除緩存. 數據表根據屬性字段來決定是否緩存 可以更換數據庫鏈接方式,比如可以隨時更換為mysql或mysqli() 當插入數據時給出一

PMO在組織實現價值應做的工作

學習 發現 html sin ont 項目管理 成本 積累 amp PMO在組織中實現價值應做的工作 研發人員及項目經理常常對PMO有反感情緒,認為其不熟悉業務流程與技術、經常要求項目經理和研發人員提交形式化的材料,只審批和監控,不能為項目提供良好的

JDBC上關於資料庫操作一對多關係和多對多關係的實現方法--轉

  原文地址---- https://www.cnblogs.com/pangguoming/p/7028322.html 黑馬程式設計師 我們知道,在設計一個Java bean的時候,要把這些BEAN 的資料存放在資料庫中的表結構,然而這些資料庫中的表直接又有些特殊

測試開發之前端——No5.HTML5單事件

表單事件 由 HTML 表單內部的動作觸發的事件。 適用於所有 HTML 5 元素,不過最常用於表單元素中: 屬性 值 描述 onblur script 當元素失去焦點時執行指令碼 onchange

介面測試系列:工作所用(三:__read_config.py檔案)

import os from common import fileUtil def __read_config(): base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) settings_file