简体   繁体   English

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

[英]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宏,它是:

  1. Prompts the user to enter specific contract numbers to be excluded 提示用户输入要排除的特定合同号
  2. Stores contract numbers 存储合同号
  3. Searches all three worksheets' contract column for the contract numbers 在所有三个工作表的合同列中搜索合同号
  4. Notes the unwanted contract details in a "summary" worksheet, which has already been created 在已创建的“摘要”工作表中记录不需要的合同详细信息
  5. Deletes the unwanted contract row entirely 完全删除不需要的合约行

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! 谢谢!

  1. Use the InputBox for inputting contract numbers (let's say, comma delimited). 使用InputBox输入合同编号(用逗号分隔)。 Split the result using Split function. 使用Split功能分割结果。
  2. Store contract numbers on a separate worksheet that you hide ( wks.visible=xlVeryHidden , where wks is a worksheet object). 将合同编号存储在隐藏的单独工作表中( wks.visible=xlVeryHidden ,其中wksworksheet对象)。
  3. Find values using a multidimensional array to store the values. 使用多维数组查找值以存储值。
  4. Print 2D array to found worksheet using rFound=saArray (where rFound is a range object and saArray is the 2D array. 使用rFound=saArray (其中rFoundrange对象,而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.

相关问题 要将单个excel工作簿中存在的232个excel工作表中的数据复制到目标工作表中,行名和工作表名应相同 - To copy data from 232 excel worksheets present in a single excel workbook into a destination worksheet.The row name and worksheet name should be same 导入 excel 工作簿中的每个工作表并保存到以工作表名称命名的 dataframe - Import every worksheet in an excel workbook and save to a dataframe named by the worksheet name 使用单元格引用作为工作簿和工作表的名称来激活Excel工作簿/工作表 - Activating Excel Workbook/Sheet using cell reference as name of Workbook and Worksheet 优秀 在不同的工作表中查找行 - excel | find row in different worksheet 在Excel中查找工作表名称映射 - Find worksheet name mapping in Excel 从Excel-VBA中的范围获取工作簿名称和工作表名称 - Get Workbook Name and Worksheet Name from a Range in Excel-VBA 如何在读取 Excel 工作簿的属性时选择正确的工作表名称 - How to pick the right worksheet name when reading properties of an excel workbook 如何通过另一个工作簿中的VBA对象名称引用Excel工作表? - How to refer to a Excel Worksheet by its VBA Object Name in another Workbook? VBA将Excel工作表以及工作簿名称和文本另存为PDF - vba save excel worksheet with workbook name plus text as a PDF 如何在 VBA 的新工作簿中为复制的工作表的名称添加数字 - How to add a number to a name of a copied worksheet in a new workbook in VBA
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM