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