查找Excel工作簿的工作表名称和行号

我正在处理包含三个数据工作表的工作簿。 每个工作表都有一个合同编号栏。 必须排除某些合同,并在单独的工作表中注明。

我想创buildExcel VBAmacros:

  1. 提示用户input要排除的特定合同号码
  2. 存储合同号码
  3. 在三个工作表的合同栏中search合同号码
  4. 在已经创build的“摘要”工作表中记下不需要的合同详细信息
  5. 完全删除不需要的合同行

macros应该循环下面的这个过程,用户input的“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 

如果合同编号在第一个WS中不存在,则会出现“对象variables或未设置块”的错误。 一旦我可以解决这个错误,我将需要通过循环运行这个过程,由用户input的每个合同号码。 任何帮助debugging错误或build立一个循环,将不胜感激。

谢谢!

  1. 使用InputBoxinput合同号码(比方说,逗号分隔)。 使用Splitfunction分割结果。
  2. 将合同号存储在您隐藏的单独工作表上( wks.visible=xlVeryHidden ,其中wksworksheet对象)。
  3. 使用multidimensional array查找值以存储值。
  4. 使用rFound=saArray二维数组打印到find的工作表(其中rFound是一个range对象, saArray是二维数组。

大量使用录制macros来学习语法。

以快速方式检索并打印到cells请参阅此示例 。

更新:

对不起,这是相当草率的,但我只是把它扔在一起,显然,它没有经过testing。 希望这可以帮助。 对不起,我也不应该让你使用这种先进的技术,但我很难回去。

 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 

我几乎没有添加Jon49的答案,似乎涵盖了基础知识。 但是我希望在早期的VBA编程生涯中发现了Forms。 起初他们可能有点混乱,但一旦掌握了,他们就会极大地增加一个macros的可用性,只需很less的努力。

表单可以用来从用户(而不是InputBox)获取值,也可以用来给用户提供进度信息。 我只会谈论第二个用法。 你的macros可能需要一些时间, 用户有时间拿一杯咖啡还是在5秒内完成? 我讨厌坐在那里的节目说:“请稍等 – 这可能需要几分钟到几个小时”。

以下代码将表单加载到内存中,并将其显示给用户,并在末尾将其从内存中移除。 如果您不卸载表单,它将在macros结束后保留​​在屏幕上,如果您想为用户留言,这可能很有用。 这种forms是显示“无模式”,这意味着macros显示它并进行。 如果显示“模式”,则macros将停止,直到用户input表单所需的任何信息。

  Load frmProgress Progress.Show vbModeless ' Main code of macro Unload frmProgress 

对于提供表单教程的网站没有任何结束,所以我将主要描述什么而不是如何。

在VB编辑器中,插入一个用户窗体。 拖动底部和右边缘,如果你想要更大。 使用属性窗口将名称更改为frmProgress。

从工具箱中拖出四个标签并排列成一行。 将标签1的标题设置为“工作表”,将标签3的标题设置为“的”。 名称标签2“lblWSNumCrnt”和名称标签4“lblWSNumTotal”。

在“for j = 0 to 2”

 frmProgress.lblWSNumTotal.Caption = 3 for j = 0 to 2 frmProgress.lblWSNumCrnt.Caption = j + 1 DoEvents 

这意味着用户将会看到下面的步骤,从n步进到1到3,

 Worksheet n of 3 

为行号添加另外四个标签,并在k循环周围添加以下代码:

 frmProgress.lblRowNumTotal.Caption = ubound(vdata, 1) for k = 1 to ubound(vdata, 1) frmProgress.lblRowNumCrnt.Caption = k DoEvents 

现在用户会看到如下所示的内容:

 Worksheet 2 of 3 Row 1456 or 2450 

上面的技巧很简单,不会对Jon49的代码做任何改变。 从Wrox的优秀的Excel VBA程序员参考中借用的以下技术稍微复杂一些,但是使您的macros更专业。

创build一个贯穿整个表单的标签。 将其命名为“lblToDo”并将其着色为白色。 在顶部创build另一个相同大小的标签。 将其命名为“lblDone”并将其颜色改为黑色。

创build一个代码的副本来计算顶部每个表中的行数,以便在执行任何其他操作之前,您可以计算总行数“TotalRowsTotal”。

创build一个新的variables“TotalRowsCrnt”,初始化为零,并为每个工作表中的每一行添加一个。

在内部循环中,添加:

 frmProgress.lblToDo.Width = _ frmProgress.lblDone.Width * TotalRowsCrnt / TotalRowsTotal 

对于我所使用的所有组织仍在使用的Excel 2003,这将为黑色“完成”标签提供一个进度条,稳定地覆盖白色“待办事项”标签。 更高版本的Excel可能会提供一个标准的进度条控件。

我希望这给你一些想法,使你的macros对用户更具吸引力。