如何根据VBA中命名的开始和结束单元格select一系列单元格?

我将数据从一个MySQL数据库拖到工作表中,方法是将其保存为csv并将该csv数据粘贴到工作表中。 这个csv保存所有客户端的所有数据,由标记单元格分隔,如“Client1:START”和“Client1:END”。 然后我运行一个macros来复制两个页面:一个来自汇总表中的各个客户端数据,另一个具有运行该数据的图表。

几乎所有工作都已经完成:复制所有页面,并更新图表和从客户端的数据表中提取信息的单元格。

剩下的唯一的事情就是把数据从汇总的表格复制到每个客户的表格中。 我给了这个很多的想法,似乎是最简单的方法来做到这一点,因为我不知道一个给定的客户端将产生的行数(零和31之间的任何东西,因为这是一个月报告)在该客户机的第一行之前的行的第一个单元格中具有“Client1:START”,并且在该行之后的第一个单元格中具有“Client1:END”。

然后,我可以直接search单元格,直到find这两个单元格,然后命名它们(因为我不知道如何将单元格地址保存在variables中),然后以某种方式将它们抵消以获得我想要的实际范围标记。

然后我可以复制该范围并将其粘贴到新创build的数据表中。

实际上,我甚至还没有得到抵消。 我仍然试图根据他们的名字来select单元格。 这是我的:

Dim Client Dim SelectedCell Dim StartCell Dim EndCell For Each Client In Array("Client1", "Client2") StartCell = Client & "StartCell" EndCell = Client & "EndCell" Sheets("ALL-DATA").Select For Each SelectedCell In Range("A1:D20") If SelectedCell.Value = Client & ":START" Then SelectedCell.Name = StartCell End If If SelectedCell.Value = Client & ":END" Then SelectedCell.Name = EndCell End If Next SelectedCell Range(StartCell & ":" & EndCell).Select '<-- This won't compile Next Client 

该范围不会让我select使用variables,所以我有点卡住了。 看来,VBA只允许您使用一串地址来select范围。

如果有人能指出我正确的方向,将不胜感激。 如果您知道如何调整select以排除实际的标记(考虑到数据为零行的可能性),那将是非常棒的,并且是一个巨大的奖励。

谢谢!

由于我在上面评论中提到的许多原因,此代码不能编译。 我相信下面的工作。 你应该习惯于总是声明你的variables,并使用Option Explicit来防止input错误/ etc。

  • 您需要一种方法来获取单元格的地址,也就是通过引用它的.Address属性:)单元格和范围没有.Name属性,所以您的代码实际上会在行上失败SelectedCell.Name = StartCell
  • 你的任务陈述是倒退的。 为了分配StartCellvariables,该variables必须位于赋值语句的左侧,如果需要表示像单元/范围那样的对象 ,则还必须使用Set关键字,即Set StartCell = Range("A1")

我也更新了这个以避免使用Select方法 。 在Excel中SelectActivate任何东西的时间是99.9%。

 Dim Client as Variant Dim SelectedCell as Range Dim StartCell as Range Dim EndCell as Range Dim ClientRange as Range For Each Client In Array("Client1", "Client2") For Each SelectedCell In Sheets("ALL-DATA").Select.Range("A1:D20") If SelectedCell.Value = Client & ":START" Then Set StartCell = SelectedCell ElseIf SelectedCell.Value = Client & ":END" Then Set EndCell = SelectedCell End If Next SelectedCell Set ClientRange = Sheets("ALL-DATA").Range(StartCell.Address & ":" & EndCell.Address) Next Client 

现在,您已将ClientRange限定为属于“All-DATA”工作表,通常不需要任何原因select或激活它。 这样做只会增加代码的不必要的操作和复杂性,并降低其性能。

如果行包含特定于客户端的单元格,则使用自动筛选器仅显示那些行。 然后做一个全选(logging)。

给你具体的问题。

为了find你的单元我logging(工具 – macros – logging新macros)编辑 – 查找

 Cells.Find(What:="fred", After:=ActiveCell, LookIn:=xlValues, LookAt:= _ xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _ , SearchFormat:=False).Activate 

你可以改变一下

 Set client = Cells.Find(What:="fred", After:=ActiveCell, LookIn:=xlValues, LookAt:= _ xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _ , SearchFormat:=False) 

我处理这个function的数量。

1)获取表的开始和结束的引用:

使用Application.Range或Me.Range查找由命名范围标识的表的开始和结束。 在这种情况下,表格有一个标题和一个脚行来标记表的开始和结束。

我将这些函数放在工作表的模块中,这使我可以使用Me.Range。 我也使用限制命名范围的范围到工作表只。

 Private Function GetTableStart() As Long GetTableStart = Me.Range("TABLE_START").Row + 1 End Function Private Function GetTableEnd() As Long GetTableEnd = Me.Range("TABLE_END").Row - 1 End Function 

我也命名列,COLUMN_ID是一个命名的范围,select工作表中的整个列。 例如它的命名范围是'Worksheet'!$ A:$ A

 Private Function GetColumnId() As Long GetColumnId = Me.Range("COLUMN_ID").Column End Function Private Function GetLastColumn() As Long GetLastColumn = Me.Range("COLUMN_LAST").Column End Function 

2)更改表格的大小。 给它你想要的行数,它会为你调整表的大小。 :

 Private Sub FixTableSize(expectedRows As Long) If expectedRows = 0 Then Err.Raise vbObjectError + 513, Me.name, "Cannot resize the table's number of rows to 0" End If Dim startRow As Long Dim endRow As Long Dim startColumn As Long Dim endColumn As Long Dim numberOfRows As Long Dim table As Range startRow = GetTableStart() endRow = GetTableEnd() startColumn = GetColumnId() endColumn = GetColumnEnd() numberOfRows = endRow - startRow + 1 Set table = Me.Range(Me.Cells(startRow, startColumn), Me.Cells(endRow, endColumn)) If numberOfRows > 0 Then ' Prevent it from clearing the headers table.ClearContents End If With Me Dim cnt As Integer If expectedRows > numberOfRows Then For cnt = 1 To (expectedRows - numberOfRows) table.Rows(2).Insert xlShiftDown Next cnt ElseIf expectedRows < numberOfRows Then For cnt = 1 To (numberOfRows - expectedRows) table.Rows(1).Delete xlShiftUp Next cnt End If End With End Sub 

3)填写表格。 一旦表格尺寸合适,我就用我想要的数据填充表格。

 Private Sub PopulateIssues(sprints() As JIRASprint) Dim currentSprint As Variant Dim currentRow As Long currentRow = GetTableStart() For Each currentSprint In sprints Me.Cells(currentRow, GetColumnId()).Value = currentSprint.Id Me.Cells(currentRow, GetColumnName()).Value = currentSprint.name Me.Cells(currentRow, GetColumnClosed()).Value = currentSprint.Closed Me.Cells(currentRow, GetColumnStartDate()).Value = currentSprint.startDate Me.Cells(currentRow, GetColumnEnd()).Value = currentSprint.endDate If currentSprint.completeDate <> 0 Then Me.Cells(currentRow, GetColumnCompleteDate()).Value = currentSprint.completeDate End If currentRow = currentRow + 1 Next End Sub 

4)然后我把它放在一个子程序称为更新表。

 Private Sub UpdateTable() On Error GoTo ErrHandler Dim numberOfRows As Long Dim sprints() As JIRASprint ' Where JIRASprint is a custom Class I made. numberOfRows = ... ' Find out how many rows I need somehow. Set sprints = GetData() ' Get the data however you want. ' turn these off so it updates faster ... Application.ScreenUpdating = False Application.Calculation = xlCalculationManual FixTableSize numberOfRows PopulateIssues sprints ' turn them back on ... Application.ScreenUpdating = True Application.Calculation = xlCalculationAutomatic Exit Sub ErrHandler: ' turn them back on ... Application.ScreenUpdating = True Application.Calculation = xlCalculationAutomatic MsgBox "An error occured while updating the worksheet" End Sub 

希望这可以帮助!