希望在excel中选择未确定的行数作为较大VBA宏的一部分

时间:2011-12-06 16:11:42

标签: excel vba excel-vba spreadsheet

我正在使用包含大量纸张的excel书;第一张表链接到外部程序并通过外部函数提取数据,导入的行数变化很大。

此块数据是通过许多后续工作表传播的。第一步是用列表1中的行数填充列A(行名称)。从这里,数据被分成多个列(当前为B-> L)。顶行使用IF()函数填充第一行,我正在寻找一个干净的宏来将此公式复制到第x行(随每次数据导入刷新而变化),然后粘贴可管理文件大小的值

这是我到目前为止所得到的;它有效,但它相当(读:非常!)笨拙:

Sub Refresh_Data()  
    Sheets("Sheet2").Select  
    ActiveWindow.ScrollWorkbookTabs Sheets:=13  
    Sheets(Array("Sheet2" ... "Sheet25")).Select     
    Sheets("Sheet2").Activate  
    Sheets("Sheet25").Select Replace:=False  
    Range("B1:L1").Select  
    Selection.Copy  
    Range("__B2:B1000__").Select  
    ActiveSheet.Paste  
    Application.Calculate  
    ActiveWindow.ScrollWorkbookTabs Position:=xlFirst  
    Sheets(Array("Sheet2" ... "Sheet25")).Select  
    Sheets("Sheet2").Activate  
    Sheets("Sheet25").Select Replace:=False  
    Sheets("Sheet2").Select  
    Range("B3").Select  
    Sheets(Array("Sheet2" ... "Sheet25")).Select  
    Sheets("Sheet2").Activate  
    Sheets("Sheet25").Select Replace:=False  
    Range("B3:L4").Select  
    Range("__B2:L1000__").Select  
    Application.CutCopyMode = False  
    Selection.Copy  
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _  
        :=False, Transpose:=False  
    Sheets("Check_sheet").Select  
    MsgBox "Update complete"  
End Sub`

我希望实现的主要功能是将代码B2:L1000替换为可以评估A列中行数的内容,并相应地选择行B到L中的范围。

由于列L是最后一个填充的列,我不明白为什么这也不能水平完成而不是定义“B:L”,因为需要添加以后的列。

2 个答案:

答案 0 :(得分:10)

虽然早期的答案有其优点:

1)我不会使用COUNTA,因为如果行或列中有空单元格,则会忽略底部或右侧的单元格。

2)在运行宏之前,我绝不会依赖用户选择要使用的正确表单;特别是有这么多床单的人。

我对这个问题的反应是你已经设置了Macro Record,在你的工作簿上闲逛然后停止了记录。你选择一件事,然后选择另一件事。滚动页面。对我来说,大多数陈述并不笨拙,毫无意义。

以下内容确实包含了有关查找A列最后一行的问题的答案,但它更多的是关于查找范围的维度,将数据从范围中取出然后将其放在其他位置的教程。这似乎是您对VBA最简单的理解所做的大部分工作。如果这种批评不公平,我很抱歉,但这是你的问题给我的印象。

Sub Test()

  Dim RowS01Max As Integer
  Dim Sheet1Data() As Variant

  ' With Sheets("Sheet1") allows you to access data within worksheet Sheet1
  ' without selecting it.
  ' Range("A1:C11") refers to a range within the active sheet
  ' .Range("A1:C11") refers to a range within the sheet identified in the
  '         With statement.
  ' ^ Note the dot
  With Sheets("Sheet1")

    ' Rows.Count is the number of rows for the version of Excel you are using.
    ' .Cells(Rows.Count, "A") address the bottom row of column A of worksheet
    ' Sheet1.
    ' .Cells(Rows.Count, 1) refer to column A by number.
    ' End(xlUp) is the VBA equivalent of Ctrl+Up.
    ' If you positioned the cursor at the bottom of column A and pressed
    ' Ctrl+Up, the cursor would jump to the last row in column A with a value.
    ' The following statement gets that row number without actually moving
    ' the cursor.
    RowS01Max = .Cells(Rows.Count, "A").End(xlUp)

    ' The following statement loads the contents of range A1:C11 of
    ' Sheets("Sheet1") into array Sheet1Data.
    Sheet1Data = .Range("A1:C11").Value

    ' This is the same statement but the range is specified in a different way.
    ' .Cells(Row,Column) identifies a single cell within the sheet specified in
    ' the With statement.  .Cells(1,1) identifies row 1, column 1 which is A1.
    '. Cells(11, "C") identifies row 11, column C which is C11.
    Sheet1Data = .Range(.Cells(1, 1), .Cells(11, "C")).Value

    ' This statement uses RowS01Max to specify the last row
    Sheet1Data = .Range(.Cells(1, 1), .Cells(RowS01Max, 1)).Value

    ' In all three examples above, the contents of the specified range will
    ' be loaded to array Sheet1Data.  Whichever range you pick, Sheet1Data
    ' will always be a two dimensional array with the first dimension being
    ' the row and the second dimension being the column.

    ' In the first two examples Sheet1Data(5,3) contains the contents
    ' of cell C5.  In the third example, I have only loaded column A but the
    ' array will still has two dimensions but the only permitted value for the
    ' second dimension is 1.

    ' The following statement writes the contents of Sheet1Data to column "E"

    .Range(.Cells(1, 5), .Cells(RowS01Max, 5)).Value = Sheet1Data

  End With

  With Sheets("Sheet2")

    ' The following statement writes the contents of Sheet1Data to column "E"
    ' of worksheet Sheet2.
    .Range(.Cells(1, 5), .Cells(RowS01Max, 5)).Value = Sheet1Data

  End With

End Sub

不要绝望!我们大多数人都从宏录制器开始,仍然使用它来发现一个不熟悉的命令的语法。看看其他问题。有些人询问异国情调的功能,但很多都是关于向有经验的程序员传递数据的简单方法。用提问者的问题设置一些工作簿。将解决方案复制并粘贴到模块中。使用F8(参见调试器)逐步执行它,在Excel和Editor之间切换,观察工作表发生的情况并将光标移到变量上以查看其当前值。花半天时间玩。你会惊讶于它开始有多快有意义。祝你好运,编程好。

答案 1 :(得分:3)

以下应该可以解决问题:

Sub Refresh_Data()
    Dim lastRow As Integer
    Dim lastCol As Integer
    Dim entireRange As Range
    Dim targetRange As Range

    lastRow = Excel.Evaluate("COUNTA(A:A)") ''// count the rows in column A
    lastCol = Excel.Evaluate("COUNTA(1:1)") ''// count the columns in row 1

    Set entireRange = Range(Cells(1, 2), Cells(lastRow, lastCol))
    Set targetRange = Range(Cells(2, 2), Cells(lastRow, lastCol))

    entireRange.FillDown
    Application.Calculate
    targetRange.Copy
    targetRange.PasteSpecial Paste:=xlPasteValues
End Sub

注意:

Excel.Evaluate(...)允许您在VBA宏中使用工作表函数的结果。

COUNTA(range)是一个工作表函数,用于计算给定范围内非空单元格的数量。在这种情况下,它可用于确定数据集中的总行数,以及第1行中包含公式的列数。