[英]Find Worksheet Name and Row Number for an Excel Workbook
I am working with a workbook that contains three worksheets of data. 我正在使用一个包含三个数据工作表的工作簿。 Each worksheet has a Contract Number column.
每个工作表都有一个“合同号”列。 Certain contracts must be excluded and noted in a separate worksheet.
某些合同必须排除在外,并在单独的工作表中注明。
I would like to create Excel VBA macro that: 我想创建Excel VBA宏,它是:
The macro should loop through this process below for 'n' number of contracts entered by the user. 宏应在用户输入的“ n”份合同下面通过此过程进行循环。
Public contString As String
Public x As Variant
Public xCount As Variant
Sub find()
contString = InputBox(Prompt:="Enter contract numbers to exclude(Comma Delimited). Cancel to include all contracts.", _
Title:="Exclude Contracts", Default:="1715478")
x = Split(contString, ",")
xCount = UBound(x) 'Number of contracts entered by user
End Sub
Sub SearchWS1()
Sheets("WS1").Activate
Columns("I:I").Select 'Contract Number Column
Selection.find(What:=x(i), After:=ActiveCell, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
BKWS = ActiveCell.Worksheet.Name
BKRow = ActiveCell.Row
If BKRow > 0 Then
Cname = Range("G" & BKRow)
Cnumber = Range("I" & BKRow)
Cvalue = Range("K" & BKRow)
'Summarize Excluded Contract Info on Summary WS
Range("Summary!B25").Value = "Exclusions:"
Range("Summary!B26").Value = Cnumber
Range("Summary!C26").Value = Cname
Range("Summary!D26").Value = Cvalue
'Select and Delete Contract
Rows(ActiveCell.Row).Select
Rows(BKRow).EntireRow.Delete
Else
Call SearchWS2 'SearchWS2 is essentially the same as SearchWS1 and Calls SearchWS3 if contract isn't found.
End If
End Sub
If the contract number doesn't exist in the first WS, I get an error like 'Object variable or With block not set'. 如果第一个WS中不存在合同编号,则会出现类似“对象变量或未设置With块”的错误。 Once I can fix this error, I will need to run this process through a loop for each contract number entered by the user.
纠正此错误后,我将需要针对用户输入的每个合同号通过一个循环运行此过程。 Any help with debugging the error or setting up a loop for this would be greatly appreciated.
调试错误或为此建立一个循环的任何帮助将不胜感激。
Thanks! 谢谢!
InputBox
for inputting contract numbers (let's say, comma delimited). InputBox
输入合同编号(用逗号分隔)。 Split the result using Split
function. Split
功能分割结果。 wks.visible=xlVeryHidden
, where wks
is a worksheet
object). wks.visible=xlVeryHidden
,其中wks
是worksheet
对象)。 rFound=saArray
(where rFound
is a range
object and saArray
is the 2D array. rFound=saArray
(其中rFound
是range
对象,而saArray
是2D数组)将2D数组打印到找到的工作表中。 Make heavy use of recording macros to learn syntax. 大量使用录制宏来学习语法。
See this example on fast ways to retrieve and print to cells
. 有关快速检索和打印到
cells
方法,请参见此示例 。
Update: 更新:
Sorry, this is pretty sloppy but I just threw it together and, obviously, it hasn't been tested. 抱歉,这很草率,但是我把它放在一起,显然,它还没有经过测试。 Hope this helps.
希望这可以帮助。 Sorry, I also shouldn't be having you use advanced techniques like this, but it's hard for me to go back.
抱歉,我也不应该让您使用像这样的高级技术,但是我很难回头。
dim j as integer, k as integer, m as long, iContractColumn as integer
Dim x() as string, saResults() as string
dim vData as variant
dim wks(0 to 2) as worksheet
iContractColumn=????
set wks(0) = Worksheets("First")
set wks(1) = Worksheets("Second")
set wks(2) = Worksheets("Third")
redim saresults(1 to 100, 1 to 2)
m=0
'Loop thru worksheets
for j=0 to 2
'Get data from worksheet
vdata=wks(j).range(wks(j) _
.cells(1,iContractColumn),wks(j).cells(rows.count,iContractColumn).end(xlup))
'Loop through data
for k=1 to ubound(vdata)
'Loop through user criteria
For i = 0 To UBound(x)
'Compare user criteria to data
if x(i)=cstr(vdata(k,1)) then
'Capture the row and worksheet name
m=m+1
'If array is too small increase size
if m>ubound(saresults) then
redim preserve saresults(1 to ubound(saresults)*2, 1 to 2)
end if
'Get name and row.
saresults(m,1)=wks(j).name
saresults(m, 2)=k
exit for
end if
next i
next k
next j
'Resize array to correct size
redim preserve saresults(1 to m, 1 to 2)
'Print results to a result page (you could also create hyperlinks here
'that would make it so the person can click and go to the respective page.
'You would have to do a loop for each result on the range.
with worksheets("Result Page")
.range(.cells(1,1),.cells(m,2))=saresults
end with
I have little to add Jon49's answer which does seem to cover the basics. 我几乎没有补充Jon49的答案,这似乎涵盖了基础知识。 But I wish I had discovered Forms earlier in my VBA programming career.
但是我希望我在VBA编程生涯的早期就发现了Forms。 They can be a little confusing at first but, once mastered, they add enormously to the usability of a macro for very little effort.
刚开始它们可能会有些混乱,但是一旦掌握了它们,只需付出很少的努力,它们就会极大地增加宏的可用性。
Forms can be used to get values from the user (instead of InputBox) or can be used to give progress information to the user. 表单可用于从用户(而不是InputBox)获取值,或可用于向用户提供进度信息。 I will only talk about the second usage.
我只会谈论第二种用法。 Your macro might take some time;
您的宏可能需要一些时间; has the user time to get a cup of coffee or will it finish in 5 seconds?
用户有时间喝杯咖啡吗,还是会在5秒内完成? I HATE programs that sit there saying "please wait - this may take from a few minutes to a few hours".
我讨厌坐在那里的程序说:“请稍等-这可能需要几分钟到几个小时”。
The following code loads a form into memory, shows it to the user and removes it from memory at the end. 以下代码将一个表单加载到内存中,向用户显示该表单,最后将其从内存中删除。 If you do not unload the form, it remains on the screen after the macro has ended which may be useful if you want to leave a message for the user.
如果您不卸载表格,则该表格将在宏结束后保留在屏幕上,如果您想向用户留言,该表格可能会很有用。 This form is show "modeless" which means the macro displays it and carries on.
这种形式显示为“无模式”,这意味着宏将显示并继续。 If shown "modal", the macro stops until the user has entered whatever information the form requires.
如果显示为“模式”,则宏将停止,直到用户输入了表单所需的任何信息。
Load frmProgress
Progress.Show vbModeless
' Main code of macro
Unload frmProgress
There are no end to the web sites offering tutorials on Forms so I will mainly describe the what rather than how. 提供有关Forms教程的网站是没有止境的,因此我将主要描述内容而不是方法。
Within the VB Editor, Insert a UserForm. 在VB编辑器中,插入一个用户窗体。 Drags the bottom and right edges if you want it bigger.
如果希望更大,则拖动底部和右侧边缘。 Use the Properties Window to change the Name to frmProgress.
使用属性窗口将名称更改为frmProgress。
Drag four labels from the Tool Box and arrange them in a line. 从工具箱中拖动四个标签,并将它们排列成一行。 Set the caption of label 1 to "Worksheet " and the caption of label 3 to "of".
将标签1的标题设置为“工作表”,将标签3的标题设置为“ of”。 Name label 2 "lblWSNumCrnt" and name label 4 "lblWSNumTotal".
名称标签2“ lblWSNumCrnt”和名称标签4“ lblWSNumTotal”。
Add the following around "for j = 0 to 2" 在“ for j = 0 to 2”周围添加以下内容
frmProgress.lblWSNumTotal.Caption = 3
for j = 0 to 2
frmProgress.lblWSNumCrnt.Caption = j + 1
DoEvents
This means the user will see the following with n stepping from 1 to 3 as the macro progesses: 这意味着随着宏的进行,用户将看到n从1跳到3的以下内容:
Worksheet n of 3
Add another four labels for row number, and the following code around the k loop: 为行号添加另外四个标签,并在k循环周围添加以下代码:
frmProgress.lblRowNumTotal.Caption = ubound(vdata, 1)
for k = 1 to ubound(vdata, 1)
frmProgress.lblRowNumCrnt.Caption = k
DoEvents
Now the user will see something like: 现在,用户将看到类似以下内容:
Worksheet 2 of 3
Row 1456 or 2450
The above technique is simple and does not involve any change to Jon49's code. 上面的技术很简单,并且不涉及Jon49的代码的任何更改。 The following technique, borrowed from Wrox's excellent Excel VBA Programmer's Reference , is a little more complicated but gives your macro a more professional appearance.
从Wrox出色的Excel VBA程序员参考中借用的以下技术稍微复杂一些,但可以使您的宏看起来更专业。
Create a label that runs across the entire form. 创建一个贯穿整个表单的标签。 Name it "lblToDo" and colour it white.
将其命名为“ lblToDo”,并将其着色为白色。 Create another label of the same size over the top.
在顶部创建另一个相同大小的标签。 Name it "lblDone" and colour it black.
将其命名为“ lblDone”并将其着色为黑色。
Create a copy of the code to count the rows in each sheet at the top so you can calculate the total number of rows, "TotalRowsTotal", before you do anything else. 创建代码副本以计算顶部每个工作表中的行,以便在执行其他操作之前可以计算总行数“ TotalRowsTotal”。
Create a new variable "TotalRowsCrnt", initialise it to zero and add one to it for every row in every worksheet. 创建一个新变量“ TotalRowsCrnt”,将其初始化为零,然后为每个工作表中的每一行添加一个变量。
Within the inner loop, add: 在内部循环中,添加:
frmProgress.lblToDo.Width = _
frmProgress.lblDone.Width * TotalRowsCrnt / TotalRowsTotal
For Excel 2003, which all the organisations I work with still use, this gives a progress bar with the black Done label steadily covering the white ToDo label. 对于Excel 2003(我与之合作的所有组织仍在使用),它提供了一个进度条,其中黑色的Done标签稳定地覆盖了白色的ToDo标签。 Later version of Excel may offer a progress bar control as standard.
Excel的更高版本可能会提供进度条控件作为标准。
I hope this gives you some ideas for making your macros more attractive to your users. 我希望这能给您一些思路,使您的宏对用户更具吸引力。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.