VBA使用列表框将选择应用于模块

VBA使用列表框将选择应用于模块,vba,excel,Vba,Excel,我对VBA比较陌生,所以提前谢谢你的建议。我只是想帮助一个朋友,让他的工作在我的空闲时间少重复 我创建了一个GUI,它有两个列表框,其中包含excel文件中工作表的名称。左侧列表框包含可用的工作表,右侧列表框是用户选择对其执行分析的工作表列表,可以在两个列表框之间移动名称。我试图将GUI链接到我创建的执行实际分析的模块。一旦它被链接,我需要在GUI中做出的选择变成一个可以在模块中循环的数组。我少了几块,请耐心点 提交按钮代码: Dim Size As Integer Size = Me.

我对VBA比较陌生,所以提前谢谢你的建议。我只是想帮助一个朋友,让他的工作在我的空闲时间少重复

我创建了一个GUI,它有两个列表框,其中包含excel文件中工作表的名称。左侧列表框包含可用的工作表,右侧列表框是用户选择对其执行分析的工作表列表,可以在两个列表框之间移动名称。我试图将GUI链接到我创建的执行实际分析的模块。一旦它被链接,我需要在GUI中做出的选择变成一个可以在模块中循环的数组。我少了几块,请耐心点


提交按钮代码:

Dim Size As Integer 
Size = Me. ListBox2 . ListCount - 1 
ReDim Selection(0 To Size) As String
Dim i As Integer

For i = 0 To Size 
    Selection (i) = Me.ListBox2.ItemData(i) 
Next i 

Unload GUI 

模块中我要实现选择的区域:

'Only performs copy/paste actions on the worksheets that aren't named "Summary".
    For Each sh In ActiveWorkbook. Worksheets 
        If sh.Name < > DestSh.Name Then 
'Sets the Range you want to Copy from the source Worksheets. This range is the set of cells with data in it.
            Set CopyRng = sh. UsedRange
”仅对未命名为“摘要”的工作表执行复制/粘贴操作。
对于Active工作簿中的每个sh。工作表
如果sh.Name<>DestSh.Name,则
'设置要从源工作表复制的范围。此范围是包含数据的单元格集。
设置CopyRng=sh.UsedRange

目标是从GUI读取选择,找到选择命名的工作表,并以某种方式将选择链接到“sh”变量。

因为您已经在代码中将
sh
作为工作表变量引用,而
选择
数组保存字符串,我认为最简单的方法是将每个语句的
转换为:

For Each sel_item In Selection
并添加以下行:

Set sh = ActiveWorkbook.Worksheets(sel_item)
当然,您还需要将
Next sh
语句编辑到
Next sel\u item
,并将
Dim sel\u item作为变量添加到


换句话说,循环部分的开头将如下所示:

'Only performs copy/paste actions on the worksheets that aren't named "Summary".
    For Each sel_item In Selection
        Set sh = ActiveWorkbook.Worksheets(sel_item)
        If sh.Name < > DestSh.Name Then 
'Sets the Range you want to Copy from the source Worksheets. This range is the set of cells with data in it.
            Set CopyRng = sh. UsedRange
”仅对未命名为“摘要”的工作表执行复制/粘贴操作。
对于选择中的每个选择项
设置sh=ActiveWorkbook.工作表(选择项)
如果sh.Name<>DestSh.Name,则
'设置要从源工作表复制的范围。此范围是包含数据的单元格集。
设置CopyRng=sh.UsedRange
代替此(原件):

”仅对未命名为“摘要”的工作表执行复制/粘贴操作。
对于Active工作簿中的每个sh。工作表
如果sh.Name<>DestSh.Name,则
'设置要从源工作表复制的范围。此范围是包含数据的单元格集。
设置CopyRng=sh.UsedRange
分隔单元格扩展 首先调整常量部分中的值,然后通读整个注释,因为可能存在一些您意想不到的问题。您可以在任何包含逗号分隔符的列上使用它,因此在您的情况下,您也可以在基列上使用它

Sub DelimitedCellExpansion()

  Const cVntWsSource As String = "Sheet1"   ' Source Worksheet Name/Index
  Const cStrSourceFirst As String = "A1"    ' Source First Cell Range of Data
  Const cVntSplit As Variant = "D"          ' Source Column Letter/Number
  Const cVntWsTarget As String = "Sheet2"   ' Target Worksheet Name/Index
  Const cStrTargetFirst As String = "B1"    ' Target First Cell Range of Data

  Const cStrSep  As String = ",,,|,,|, ,"   ' Wrong Separators

  Dim vntSrc As Variant       ' Source Array
  Dim vntSep As Variant       ' Separator Array
  Dim vntSplitData As Variant ' Split Data Array
  Dim vntSplit As Variant     ' Split Array
  Dim vntCol As Variant       ' Target Column Array
  Dim vntTgt As Variant       ' Target Array

  Dim intCol As Integer       ' Source Array Target Column
  Dim lng1 As Long            ' Source Array Target Column Rows Count(er)
  Dim int1 As Integer         ' Separator Array Strings Counter
  Dim lng2 As Long            ' Target Array Rows Count(er)
  Dim int2 As Integer         ' Split Data Column Counter

  ' Source Worksheet Data Extraction
  With ThisWorkbook.Worksheets(cVntWsSource)
    If Not .Cells.Find("*", .Cells(.Rows.Count, .Columns.Count), -4123, , 1) _
        Is Nothing Then   ' Worksheet has data.
      ' Paste Source Range into Source Array
      vntSrc = .Range(cStrSourceFirst, .Cells(.Cells.Find("*", , , , 1, 2) _
          .Row, .Cells.Find("*", , , , 2, 2).Column))
      ' Calculate Source Array Target Column.
      intCol = .Columns(cVntSplit).Column - .Range(cStrSourceFirst).Column + 1
     Else                 ' Worksheet is empty.
      GoTo EmptySheetErr
    End If
  End With

  ' Split Separator String into Separator Array.
  vntSep = Split(cStrSep, "|")

  ' Introduce Split Data Array
  ReDim vntSplitData(1 To UBound(vntSrc))

  ' Target Array Columns Count
  For lng1 = 1 To UBound(vntSrc)
    ' Clean separators in current field of Target Column.
    vntSrc(lng1, intCol) = WorksheetFunction.trim(vntSrc(lng1, intCol))
    For int1 = 0 To UBound(vntSep)
      vntSrc(lng1, intCol) = Replace(vntSrc(lng1, intCol), _
          vntSep(int1), ",")
    Next
    ' Split current field of Target Column.
    vntSplit = Split(vntSrc(lng1, intCol), ",")
    ' Resize Target Column Array.
    If Not IsEmpty(vntCol) Then
      ReDim Preserve vntCol(1 To UBound(vntCol) + UBound(vntSplit) + 1)
     Else
      ReDim vntCol(1 To UBound(vntSplit) + 1)
    End If
    ' Copy split values to Target Column Array.
    For int1 = 0 To UBound(vntSplit)
      vntCol(UBound(vntCol) - UBound(vntSplit) + int1) = trim(vntSplit(int1))
    Next
    ' Collect Split Data.
    vntSplitData(lng1) = UBound(vntSplit) + 1
  Next

  Erase vntSplit
  Erase vntSep

  ' Write data to Target Array
  lng2 = 1
  ReDim vntTgt(1 To UBound(vntCol), 1 To UBound(vntSrc, 2))
  For lng1 = 1 To UBound(vntSrc)
    ' Write current row of other columns to Target Array.
    Select Case intCol
      Case 1 ' LBound(vntSrc, 2)
        For int1 = 2 To UBound(vntSrc, 2)
          vntTgt(lng2, int1) = vntSrc(lng1, int1)
        Next
      Case UBound(vntSrc, 2)
        For int1 = 1 To UBound(vntSrc, 2) - 1
          vntTgt(lng2, int1) = vntSrc(lng1, int1)
        Next
      Case Else
        For int1 = 1 To intCol - 1
          vntTgt(lng2, int1) = vntSrc(lng1, int1)
        Next
        For int1 = intCol + 1 To UBound(vntSrc, 2)
          vntTgt(lng2, int1) = vntSrc(lng1, int1)
        Next
    End Select
    ' Write current row of Source Array Target Column to Target Array.
    For int2 = 1 To vntSplitData(lng1)
      vntTgt(lng2, intCol) = vntCol(lng2)
      lng2 = lng2 + 1
    Next
  Next
  Erase vntCol

'  With ThisWorkbook.Worksheets(cVntWsTarget)
'  ' Paste Target Array into Target Worksheet.
'    .Range(cStrTargetFirst).Resize(UBound(vntTgt), UBound(vntTgt, 2)) = vntTgt
'  End With

  ' This would have been the end, if there was no formatting to do.

  ' Introducing a Range object.
  Dim objRng As Range
  Set objRng = ThisWorkbook.Worksheets(cVntWsTarget) _
      .Range(cStrTargetFirst).Resize(UBound(vntTgt), UBound(vntTgt, 2))

'***************************************
' This is necessary if there are merged cells in the Target Range.
' This clears the whole Target Worksheet.
  objRng.Parent.Cells.Clear
' This clears only the Target Range.
'  objRng.Cells.Clear
'***************************************

  ' Paste Target Array into Target Range of  Target Worksheet.
  objRng = vntTgt
  Erase vntTgt

  With objRng
    ' Paste formatting from first row down to the last.
    .Cells(1, 1).Resize(, .Columns.Count).Copy ' Copy first row.
    .PasteSpecial Paste:=xlPasteFormats        ' Paste formatting down to last.
    ' The Target Range is selected and is flickering. Therefore:
    Application.CutCopyMode = False ' Target Range still selected.

'***********************************************************
    ' Apply formatting (merge)
'***********************************************************

' This is up to you. I have done only some easy formatting.

'    With .Interior
'      .ColorIndex = xlNone
'      .Pattern = xlSolid
'      .PatternColorIndex
'    End With

'    ' Font
'    With .Font
'      .Name = "Verdana"
'      .Size = 10
'      .Strikethrough = False
'      .Superscript = False
'      .Subscript = False
'      .OutlineFont = False
'      .Shadow = False
'      .Underline = xlUnderlineStyleNone
'      .ColorIndex = xlAutomatic
'      .Bold = True
'    End With

' Borders
    With .Borders(xlEdgeLeft)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlEdgeTop)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlEdgeBottom)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlEdgeRight)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlInsideVertical)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlInsideHorizontal)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With

    lng2 = 1
    For lng1 = 1 To UBound(vntSrc)
      ' Write current row of other columns to Target Array.
      Select Case intCol
        Case 1 ' LBound(vntSrc, 2)
          For int1 = 2 To UBound(vntSrc, 2): GoSub OtherFormat: Next
        Case UBound(vntSrc, 2)
          For int1 = 1 To UBound(vntSrc, 2) - 1: GoSub OtherFormat: Next
        Case Else
          For int1 = 1 To intCol - 1: GoSub OtherFormat: Next
          For int1 = intCol + 1 To UBound(vntSrc, 2): GoSub OtherFormat: Next
      End Select
      GoSub TargetFormat
      lng2 = lng2 + vntSplitData(lng1)
    Next

    Erase vntSplitData
    Erase vntSrc

    GoTo FormatEnd
'***********************************************************
' This is created to easily adjust (change) formatting.
' The formatting applies only to the Data range.
'***********************************************************
OtherFormat:    ' Format other columns.
  With .Cells(lng2, int1).Resize(vntSplitData(lng1))
    If vntSplitData(lng1) > 1 Then  ' Multiple rows.
      .HorizontalAlignment = xlCenter
      .VerticalAlignment = xlCenter
      .WrapText = False
      .Orientation = 0
      .AddIndent = False
      .IndentLevel = 0
      .ShrinkToFit = False
      .ReadingOrder = xlContext
      .MergeCells = True
     Else                           ' One row only.
      .HorizontalAlignment = xlCenter
      .VerticalAlignment = xlBottom
      .WrapText = False
      .Orientation = 0
      .AddIndent = False
      .IndentLevel = 0
      .ShrinkToFit = False
      .ReadingOrder = xlContext
      .MergeCells = False
    End If
  End With
  Return
TargetFormat:   ' Format Target Column.
  With .Cells(lng2, intCol).Resize(vntSplitData(lng1))
    .HorizontalAlignment = xlCenter
    .VerticalAlignment = xlBottom
    .WrapText = False
    .Orientation = 0
    .AddIndent = False
    .IndentLevel = 0
    .ShrinkToFit = False
    .ReadingOrder = xlContext
    .MergeCells = False
  End With
  Return
FormatEnd:

    ' Only autofits the Target Range.
'    .Columns.AutoFit
    ' Autofit from top.
    .Columns.EntireColumn.AutoFit

'***********************************************************

  End With

ProcedureExit:
  Set objRng = Nothing
Exit Sub

EmptySheetErr:
  MsgBox "You're in an empty sheet."
  GoTo ProcedureExit

End Sub

您希望对列表框中的工作表做什么?所选工作表(摘要工作表列表框中的工作表)将被复制并重新格式化为创建的“摘要”工作表。一旦每个工作表中的数据出现在摘要页面上,就会对数据执行一些基本操作,然后对数据进行格式化以供显示使用。我的代码在没有GUI的情况下运行良好。我只需要将GUI中的选择进行转换,以告诉主模块要查找哪些工作表。
Selections
声明在哪里?它是一个全局变量还是一个userform变量?我把它作为全局变量放在主模块中,与userform分开。我已经给出了答案。看看底部。这解决了一个主要的潜在问题。我还发现私有/公共子变量和变量存在问题。我把它都熨好了。非常感谢!
Sub DelimitedCellExpansion()

  Const cVntWsSource As String = "Sheet1"   ' Source Worksheet Name/Index
  Const cStrSourceFirst As String = "A1"    ' Source First Cell Range of Data
  Const cVntSplit As Variant = "D"          ' Source Column Letter/Number
  Const cVntWsTarget As String = "Sheet2"   ' Target Worksheet Name/Index
  Const cStrTargetFirst As String = "B1"    ' Target First Cell Range of Data

  Const cStrSep  As String = ",,,|,,|, ,"   ' Wrong Separators

  Dim vntSrc As Variant       ' Source Array
  Dim vntSep As Variant       ' Separator Array
  Dim vntSplitData As Variant ' Split Data Array
  Dim vntSplit As Variant     ' Split Array
  Dim vntCol As Variant       ' Target Column Array
  Dim vntTgt As Variant       ' Target Array

  Dim intCol As Integer       ' Source Array Target Column
  Dim lng1 As Long            ' Source Array Target Column Rows Count(er)
  Dim int1 As Integer         ' Separator Array Strings Counter
  Dim lng2 As Long            ' Target Array Rows Count(er)
  Dim int2 As Integer         ' Split Data Column Counter

  ' Source Worksheet Data Extraction
  With ThisWorkbook.Worksheets(cVntWsSource)
    If Not .Cells.Find("*", .Cells(.Rows.Count, .Columns.Count), -4123, , 1) _
        Is Nothing Then   ' Worksheet has data.
      ' Paste Source Range into Source Array
      vntSrc = .Range(cStrSourceFirst, .Cells(.Cells.Find("*", , , , 1, 2) _
          .Row, .Cells.Find("*", , , , 2, 2).Column))
      ' Calculate Source Array Target Column.
      intCol = .Columns(cVntSplit).Column - .Range(cStrSourceFirst).Column + 1
     Else                 ' Worksheet is empty.
      GoTo EmptySheetErr
    End If
  End With

  ' Split Separator String into Separator Array.
  vntSep = Split(cStrSep, "|")

  ' Introduce Split Data Array
  ReDim vntSplitData(1 To UBound(vntSrc))

  ' Target Array Columns Count
  For lng1 = 1 To UBound(vntSrc)
    ' Clean separators in current field of Target Column.
    vntSrc(lng1, intCol) = WorksheetFunction.trim(vntSrc(lng1, intCol))
    For int1 = 0 To UBound(vntSep)
      vntSrc(lng1, intCol) = Replace(vntSrc(lng1, intCol), _
          vntSep(int1), ",")
    Next
    ' Split current field of Target Column.
    vntSplit = Split(vntSrc(lng1, intCol), ",")
    ' Resize Target Column Array.
    If Not IsEmpty(vntCol) Then
      ReDim Preserve vntCol(1 To UBound(vntCol) + UBound(vntSplit) + 1)
     Else
      ReDim vntCol(1 To UBound(vntSplit) + 1)
    End If
    ' Copy split values to Target Column Array.
    For int1 = 0 To UBound(vntSplit)
      vntCol(UBound(vntCol) - UBound(vntSplit) + int1) = trim(vntSplit(int1))
    Next
    ' Collect Split Data.
    vntSplitData(lng1) = UBound(vntSplit) + 1
  Next

  Erase vntSplit
  Erase vntSep

  ' Write data to Target Array
  lng2 = 1
  ReDim vntTgt(1 To UBound(vntCol), 1 To UBound(vntSrc, 2))
  For lng1 = 1 To UBound(vntSrc)
    ' Write current row of other columns to Target Array.
    Select Case intCol
      Case 1 ' LBound(vntSrc, 2)
        For int1 = 2 To UBound(vntSrc, 2)
          vntTgt(lng2, int1) = vntSrc(lng1, int1)
        Next
      Case UBound(vntSrc, 2)
        For int1 = 1 To UBound(vntSrc, 2) - 1
          vntTgt(lng2, int1) = vntSrc(lng1, int1)
        Next
      Case Else
        For int1 = 1 To intCol - 1
          vntTgt(lng2, int1) = vntSrc(lng1, int1)
        Next
        For int1 = intCol + 1 To UBound(vntSrc, 2)
          vntTgt(lng2, int1) = vntSrc(lng1, int1)
        Next
    End Select
    ' Write current row of Source Array Target Column to Target Array.
    For int2 = 1 To vntSplitData(lng1)
      vntTgt(lng2, intCol) = vntCol(lng2)
      lng2 = lng2 + 1
    Next
  Next
  Erase vntCol

'  With ThisWorkbook.Worksheets(cVntWsTarget)
'  ' Paste Target Array into Target Worksheet.
'    .Range(cStrTargetFirst).Resize(UBound(vntTgt), UBound(vntTgt, 2)) = vntTgt
'  End With

  ' This would have been the end, if there was no formatting to do.

  ' Introducing a Range object.
  Dim objRng As Range
  Set objRng = ThisWorkbook.Worksheets(cVntWsTarget) _
      .Range(cStrTargetFirst).Resize(UBound(vntTgt), UBound(vntTgt, 2))

'***************************************
' This is necessary if there are merged cells in the Target Range.
' This clears the whole Target Worksheet.
  objRng.Parent.Cells.Clear
' This clears only the Target Range.
'  objRng.Cells.Clear
'***************************************

  ' Paste Target Array into Target Range of  Target Worksheet.
  objRng = vntTgt
  Erase vntTgt

  With objRng
    ' Paste formatting from first row down to the last.
    .Cells(1, 1).Resize(, .Columns.Count).Copy ' Copy first row.
    .PasteSpecial Paste:=xlPasteFormats        ' Paste formatting down to last.
    ' The Target Range is selected and is flickering. Therefore:
    Application.CutCopyMode = False ' Target Range still selected.

'***********************************************************
    ' Apply formatting (merge)
'***********************************************************

' This is up to you. I have done only some easy formatting.

'    With .Interior
'      .ColorIndex = xlNone
'      .Pattern = xlSolid
'      .PatternColorIndex
'    End With

'    ' Font
'    With .Font
'      .Name = "Verdana"
'      .Size = 10
'      .Strikethrough = False
'      .Superscript = False
'      .Subscript = False
'      .OutlineFont = False
'      .Shadow = False
'      .Underline = xlUnderlineStyleNone
'      .ColorIndex = xlAutomatic
'      .Bold = True
'    End With

' Borders
    With .Borders(xlEdgeLeft)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlEdgeTop)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlEdgeBottom)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlEdgeRight)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlInsideVertical)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With
    With .Borders(xlInsideHorizontal)
      .LineStyle = xlContinuous
      .Weight = xlThin
      .ColorIndex = xlAutomatic
    End With

    lng2 = 1
    For lng1 = 1 To UBound(vntSrc)
      ' Write current row of other columns to Target Array.
      Select Case intCol
        Case 1 ' LBound(vntSrc, 2)
          For int1 = 2 To UBound(vntSrc, 2): GoSub OtherFormat: Next
        Case UBound(vntSrc, 2)
          For int1 = 1 To UBound(vntSrc, 2) - 1: GoSub OtherFormat: Next
        Case Else
          For int1 = 1 To intCol - 1: GoSub OtherFormat: Next
          For int1 = intCol + 1 To UBound(vntSrc, 2): GoSub OtherFormat: Next
      End Select
      GoSub TargetFormat
      lng2 = lng2 + vntSplitData(lng1)
    Next

    Erase vntSplitData
    Erase vntSrc

    GoTo FormatEnd
'***********************************************************
' This is created to easily adjust (change) formatting.
' The formatting applies only to the Data range.
'***********************************************************
OtherFormat:    ' Format other columns.
  With .Cells(lng2, int1).Resize(vntSplitData(lng1))
    If vntSplitData(lng1) > 1 Then  ' Multiple rows.
      .HorizontalAlignment = xlCenter
      .VerticalAlignment = xlCenter
      .WrapText = False
      .Orientation = 0
      .AddIndent = False
      .IndentLevel = 0
      .ShrinkToFit = False
      .ReadingOrder = xlContext
      .MergeCells = True
     Else                           ' One row only.
      .HorizontalAlignment = xlCenter
      .VerticalAlignment = xlBottom
      .WrapText = False
      .Orientation = 0
      .AddIndent = False
      .IndentLevel = 0
      .ShrinkToFit = False
      .ReadingOrder = xlContext
      .MergeCells = False
    End If
  End With
  Return
TargetFormat:   ' Format Target Column.
  With .Cells(lng2, intCol).Resize(vntSplitData(lng1))
    .HorizontalAlignment = xlCenter
    .VerticalAlignment = xlBottom
    .WrapText = False
    .Orientation = 0
    .AddIndent = False
    .IndentLevel = 0
    .ShrinkToFit = False
    .ReadingOrder = xlContext
    .MergeCells = False
  End With
  Return
FormatEnd:

    ' Only autofits the Target Range.
'    .Columns.AutoFit
    ' Autofit from top.
    .Columns.EntireColumn.AutoFit

'***********************************************************

  End With

ProcedureExit:
  Set objRng = Nothing
Exit Sub

EmptySheetErr:
  MsgBox "You're in an empty sheet."
  GoTo ProcedureExit

End Sub