无法引用工作表行。仅返回当前工作表的行数据

时间:2018-10-21 20:09:51

标签: excel vba excel-vba

我对VBA和编码一般还是很陌生。我在这段代码中苦苦挣扎,我想复制表“ System 1”中A行中的数据,并在验证列表中使用它。但是,使用当前的这段代码,似乎我是从当前工作表而不是从工作表“ System 1”中获取行数据

我在这里做错了什么?参考其他工作表以优化excel速度表时的最佳实践是什么?

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

Dim range1 As Range, rng As Range
Set Sheet = Sheets("System 1")

Set range1 = Sheets("System 1").Range("A1:BB1")
Set rng = Range("M2")

With rng.Validation
     .Delete 'delete previous validation
     .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
     Formula1:="='" & Name & "'!" & .range1.Address
End With

1 个答案:

答案 0 :(得分:0)

信息太少!?

此代码应为您提供一个良好的开端。修复并调整您的需求。仔细研究代码的自定义部分。 “ WSChange ”应该可以正常运行,除了那些公共变量可能有些怪异(您总是可以将它们放入过程中……而事件却是……我不明白它们,但是我很快就会知道。如果我发现了一些改进,我将编辑答案并发布一条消息。

我差点忘了。您不能使用其他工作表中的范围来将其用作验证范围(类似于条件格式,适用于Excel 2003),因此必须定义一个名称来用作范围。

这是一个模块。我只是在工作表中看不到它。抱歉。

Option Explicit

Public strMain As String
Public Const cStrValList As String = "ValList" 'Validation List Name

Sub WSChange()

'-- Customize BEGIN --------------------
  'Name of the main worksheet containing the validation RANGE.
'***  The worksheet should be defined by name so that this script can be run ***
'***  from other worksheets (Do NOT use the Activesheet, if not necessary).  ***                                          ***
  Const cStrMain As String = "Main" 'If "" then Activesheet is used.
  'Name of the worksheet containing the validation LIST.
  Const cStrSys As String = "System 1"
'***  The next two constants should be defined as first cell ranges, so when ***
'***  adding new data, the last cell could be calculated again and the data  ***                                          ***
'***  wouldn't be 'out of bounds' (outside the range(s)).
  'Validation RANGE Address. Can be range or first cell range address.
  Const cStrMainRng As String = "$M$2" 'orig. "$M$2"
  'Validation LIST Range Address. Can be range or first cell range address.
  Const cStrSysRng As String = "$A$1" 'orig. "$A$1:$BB$1"
'-- Customize END ----------------------
  strMain = cStrMain

  Dim oWsMain As Worksheet
  Dim oRngMain As Range
  Dim oWsSys As Worksheet
  Dim oRngSys As Range
  Dim oName As Name

  Dim strMainRng As String
  Dim strMainLast As String
  Dim strSysRng As String
  Dim strSysLast As String
'---------------------------------------
  On Error GoTo ErrorHandler 'No error handling so far!
'---------------------------------------
'Main Worksheet
  If cStrMain <> "" Then 'When cStrMain is used as the worksheet name.
    Set oWsMain = ThisWorkbook.Worksheets(cStrMain)
   Else 'cStrMain = "", When ActiveSheet is used instead. Not recommended.
    Set oWsMain = ThisWorkbook.ActiveSheet
  End If
  With oWsMain
    If .Range(cStrMainRng).Cells.Count <> 1 Then
      strMainRng = cStrMainRng
     Else
      'Calculate Validation Range Last Cell Address
      strMainLast = .Range(Cells(Rows.Count, _
          .Range(cStrMainRng).Column).Address).End(xlUp).Address
      'Calculate Validation Range and assign to a range variable
      strMainRng = cStrMainRng & ":" & strMainLast 'First:Last
    End If
    Set oRngMain = .Range(strMainRng) 'Validation Range
  End With
'---------------------------------------
'System Worksheet
  Set oWsSys = Worksheets(cStrSys) 'Worksheet with Validation List
  With oWsSys
    If .Range(cStrSysRng).Cells.Count <> 1 Then
      strSysRng = cStrSysRng
     Else
      'Calculate Validation Range Last Cell Address
      strSysLast = .Range(Cells(.Range(cStrSysRng).Row, _
          Columns.Count).Address).End(xlToLeft).Address
      'Calculate Validation Range and assign to a range variable
      strSysRng = cStrSysRng & ":" & strSysLast 'First:Last
    End If
    Set oRngSys = .Range(strSysRng) 'Validation List Range
  End With
'---------------------------------------
'Name
  For Each oName In ThisWorkbook.Names
    If oName.Name = cStrValList Then
      oName.Delete
      Exit For 'If found, Immediately leave the For Each Next loop.
    End If
  Next
  ThisWorkbook.Names.Add Name:=cStrValList, RefersTo:="='" & cStrSys _
      & "'!" & strSysRng
  With oRngMain.Validation
      .Delete 'delete previous validation
      .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
          xlBetween, Formula1:="=" & cStrValList
  End With
'---------------------------------------
ProcedureExit:
  Set oRngMain = Nothing
  Set oRngSys = Nothing
  Set oWsSys = Nothing
  Set oWsMain = Nothing
Exit Sub
'---------------------------------------
ErrorHandler:
  'Handle Errors!
  MsgBox "An error has occurred.", vbInformation
GoTo ProcedureExit
'---------------------------------------
End Sub

还有一些“ 事件”,虽然不太好,但是我已经忍耐不住了。
这实际上进入了“ 系统1 ”工作表。您也许应该为“主”表找出类似的东西。

Option Explicit

Public PreviousTarget As Variant

Private Sub Worksheet_Change(ByVal Target As Range)
'MsgBox Target.Cells.Count

'-- Customize BEGIN --------------------
  Const cStr1 = "Validation List Change"
  Const cStr2 = "Values have changed"
  Const cStr3 = "Previous Value"
  Const cStr4 = "Current Value"
'-- Customize END ----------------------

  Dim str1 As String

'Values in the NAMED RANGE (cStrValList)
  'Only if a cell in the named range has been 'addressed' i.e. a cell is
  'selected and you start typing or you click in the fomula bar, and then
  'enter is pressed, this will run which still doesn't mean the value has
  'been changed i.e. the same value has been written again... If the escape
  'key is used it doesn't run.
  If Not Intersect(Target, Range(cStrValList)) Is Nothing Then
    If Target.Cells.Count > 1 Then
      WSChange
      MsgBox "Cannot handle multiple cells, yet."
     Else
      'Check if the value has changed.
      If PreviousTarget <> Target.Value Then  'The value has changed.
        WSChange
        str1 = cStr1 & vbCrLf & vbCrLf & cStr2 & ":" & vbCrLf & vbCrLf & "'" & _
            Target.Address & "' " & cStr3 & " = '"
        str1 = str1 & PreviousTarget & "'" & vbCrLf & "'" & Target.Address
        str1 = str1 & "' " & cStr4 & " = '" & Target.Value & "'."
        MsgBox str1, vbInformation
       Else 'The value has not changed.
      End If
    End If
   Else 'The cell range is out of bounds.
  End If

'Values in the NAMED RANGE ROW outside the NAMED RANGE (cStrValList9
  Dim strOutside As String
  'Here comes some bad coding.
  strOutside = Range(cStrValList).Address
  strOutside = Split(strOutside, ":")(1)
  strOutside = Range(strOutside).Offset(0, 1).Address
  strOutside = strOutside & ":" _
      & Cells(Range(strOutside).Row, Columns.Count).Address
  If Not Intersect(Target, Range(strOutside)) Is Nothing Then
    If Target.Cells.Count > 1 Then
      WSChange
      MsgBox "Cannot handle multiple cells, yet."
     Else
      If PreviousTarget <> Target.Value Then 'The value has changed.
        If strMain <> "" Then
          WSChange
         Else
          MsgBox "You have to define a worksheet by name under 'cStrMain'."
        End If
      End If
    End If
  End If
End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  'This gets the 'previous' Target value. This is gold concerning the speed of
  'execution. It's a MUST REMEMBER.
  PreviousTarget = Target.Value
End Sub

Sub vallister()
  MsgBox Range(cStrValList).Address
End Sub
Sub sdaf()
End Sub

快乐的编码。