英文:
Adding Tables using Excel VBA
问题
我想要在这些新工作表中添加新工作表和表格,并使用vba。如下图所示,有两列主类别
和子类别
。我想为每个主类别
创建新工作表,并根据它所属的工作表添加表格。此外,我可能会向主类别
和子类别
添加新条目
,vba代码应该为这些也添加工作表和表格。
Sub CreateSheetsFromAList()
' 代码部分不要翻译
End Sub
Function SheetExists(shtName As String, Optional wb As Workbook) As Boolean
' 代码部分不要翻译
End Function
Public Sub ChooseSheet(ByVal SheetName As String)
' 代码部分不要翻译
End Sub
最终结果如下图所示:
这是我的示例工作簿,没有任何代码:链接
英文:
I want to add new sheets and add tables in these new sheets, using vba. As shown in the image below, there are two column Main Category
and Sub Category
. I want to create new sheet for every Main Category
and add tables for every Sub Category
based on the sheet it belongs to. Additionally I may add new entries
to Main Category
and Sub Category
, the vba code should add sheet and tables for those as well.
<br><br>
<hr>
So far I am able to add the new sheets , but couldn't add the tables , This is what I have:
Sub CreateSheetsFromAList()
Dim MyCell As Range, myRange As Range
Dim MyCell1 As Range, myRange1 As Range
Dim WSname As String
Sheet1.Select
Range("A2").Select
Range(ActiveCell, ActiveCell.End(xlDown)).Select
Set myRange = Selection
Application.ScreenUpdating = False
For Each MyCell In myRange
If Len(MyCell.Text) > 0 Then
'Check if sheet exists
If Not SheetExists(MyCell.Value) Then
'run new reports code until before Else
Sheets.Add After:=Sheets(Sheets.Count) 'creates a new worksheet
Sheets(Sheets.Count).Name = MyCell.Value ' renames the new worksheet
WSname = MyCell.Value 'stores newly created sheetname to a string variable
'filters consolidated sheet based on newly created sheetname
Sheet3.Select
Range("A:T").AutoFilter
Range("D1").Select
Range("D1").AutoFilter Field:=4, Criteria1:=WSname, Operator:=xlFilterValues
Range("A1:U1").Select
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
Range("A1:U" & lastRow).Select
Selection.Copy 'copies filtered data
'search and activate WSname
ChooseSheet WSname
Range("AH2").Select
ActiveCell.PasteSpecial xlPasteValues
Range("AJ:AJ").Select
Selection.NumberFormat = "hh:mm"
Range("B2").Select
End If
End If
Next MyCell
End Sub
Function SheetExists(shtName As String, Optional wb As Workbook) As Boolean
Dim sht As Worksheet
If wb Is Nothing Then Set wb = ThisWorkbook
On Error Resume Next
Set sht = wb.Sheets(shtName)
On Error GoTo 0
SheetExists = Not sht Is Nothing
End Function
Public Sub ChooseSheet(ByVal SheetName As String)
Sheets(SheetName).Select
End Sub
End result looks like this:
Here's my sample workbook without any codes: https://drive.google.com/file/d/16logfbrvoK3CVKb-j-g4167pvU_BoWYI/view?usp=sharing
答案1
得分: 1
这个方法应该可以帮助你入门。
> 注意:代码注释中有一些待办事项。
步骤:
- 将你的数据库范围转换为一个名为 "TableDatabase" 的Excel结构化表。
请参阅这篇文章
- 在名为 "Database" 的工作表后添加以下代码:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = False
DatabaseManager.Change Target
Application.ScreenUpdating = True
End Sub
-
添加一个模块并将其命名为 "DatabaseManager"
-
在 "DatabaseManager" 模块中添加以下代码:
Option Explicit
Private Const DATABASE_TABLE_NAME As String = "TableDatabase"
Private Const DATABASE_MAINCAT_COLUMN_HEADER As String = "Main Category"
Private Const DATABASE_SUBCAT_COLUMN_HEADER As String = "Sub Category"
Private Const TABLE_OFFSET_ROWS As Long = 5
Private Const TABLE_COLUMN_LOCATION As Long = 1 ' 1 = A
Public Sub Change(ByVal Target As Range)
Dim databaseTable As ListObject
Dim tableRow As Long
Set databaseTable = Range(DATABASE_TABLE_NAME).ListObject
Select Case True
Case Not Intersect(Target, databaseTable.ListColumns(DATABASE_MAINCAT_COLUMN_HEADER).DataBodyRange) Is Nothing
' TODO: 验证是否添加、更新或删除主要类别
' Case: 添加主要类别工作表
AddSheetByTitle Target.Value2, Target.Parent
' TODO: 更新、删除情况
Case Not Intersect(Target, databaseTable.ListColumns(DATABASE_SUBCAT_COLUMN_HEADER).DataBodyRange) Is Nothing
' TODO: 验证是否添加、更新或删除子类别
tableRow = Target.Row - databaseTable.HeaderRowRange.Row + 1
' Case: 添加子类别表
AddTableInSheetByName databaseTable.ListColumns(DATABASE_MAINCAT_COLUMN_HEADER).Range(tableRow), Target.Value2, Target.Parent
' TODO: 更新、删除情况
Case Else
End Select
End Sub
Public Function AddSheetByTitle(ByVal Title As String, Optional ByVal ReturnSheet As Worksheet) As Worksheet
' TODO: 验证工作表名称是否有效
If SheetExists(Title) = True Then Exit Function
Dim newWorksheet As Worksheet
Set newWorksheet = ThisWorkbook.Worksheets.Add(after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
' 重命名新工作表
newWorksheet.Name = Title
' 返回到以前的工作表
If Not ReturnSheet Is Nothing Then ReturnSheet.Activate
Set AddSheetByTitle = newWorksheet
End Function
Public Function AddTableInSheetByName(ByVal TargetSheetName As String, ByVal TableName As String, Optional ByVal ReturnSheet As Worksheet) As ListObject
Dim targetSheet As Worksheet
Dim targetTable As ListObject
Dim lastRow As Long
If SheetExists(TargetSheetName) = False Then
Set targetSheet = AddSheetByTitle(TargetSheetName)
End If
If TableExists(TableName) = True Then Exit Function
Set targetSheet = ThisWorkbook.Worksheets(TargetSheetName)
lastRow = targetSheet.Cells(targetSheet.Rows.Count, 1).End(xlUp).Row
Set targetTable = targetSheet.ListObjects.Add(SourceType:=xlSrcRange, Source:=targetSheet.Cells(lastRow, TABLE_COLUMN_LOCATION).Offset(TABLE_OFFSET_ROWS))
targetTable.Name = TableName
' 设置表头和内容
targetTable.HeaderRowRange.Cells(1).Value2 = TableName
' 返回到以前的工作表
If Not ReturnSheet Is Nothing Then ReturnSheet.Activate
End Function
Private Function SheetExists(ByVal SheetName As String) As Boolean
Dim evalSheet As Worksheet
On Error Resume Next
Set evalSheet = ThisWorkbook.Sheets(SheetName)
On Error GoTo 0
SheetExists = (Not evalSheet Is Nothing)
End Function
Private Function TableExists(ByVal TableName As String) As Boolean
Dim evalTable As ListObject
Dim evalName As String
' TODO: 检查 TableName 是否有效(搜索无效字符)
evalName = Replace(TableName, " ", "_")
On Error Resume Next
TableExists = (Range(evalName).ListObject.Name = TableName)
On Error GoTo 0
End Function
> 注意:你的最终结果属于特定类型的表格。我的代码
> (正如你最初要求的)将一个新表格添加到工作表中。另一种方法是复制(复制)源表格并重命名它。
希望这有所帮助。如果有帮助,请记得标记答案。
英文:
This approach should get you started.
> Note: There are several TODOs in the code's comments.
Steps:
- Convert your database range to an Excel structured table called (TableDatabase).
See this article
-
Add this code behind the sheet "Database"
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = False DatabaseManager.Change Target Application.ScreenUpdating = True
End Sub
- Add a module and call it "DatabaseManager"
-
Add this code to the DatabaseManager module:
Option Explicit
Private Const DATABASE_TABLE_NAME As String = "TableDatabase"
Private Const DATABASE_MAINCAT_COLUMN_HEADER As String = "Main Category"
Private Const DATABASE_SUBCAT_COLUMN_HEADER As String = "Sub Category"Private Const TABLE_OFFSET_ROWS As Long = 5
Private Const TABLE_COLUMN_LOCATION As Long = 1 ' 1 = APublic Sub Change(ByVal Target As Range)
Dim databaseTable As ListObject Dim tableRow As Long Set databaseTable = Range(DATABASE_TABLE_NAME).ListObject Select Case True Case Not Intersect(Target, databaseTable.ListColumns(DATABASE_MAINCAT_COLUMN_HEADER).DataBodyRange) Is Nothing ' TODO: Validate if adding, updating or deleting a main category ' Case: Add a main category sheet AddSheetByTitle Target.Value2, Target.Parent ' TODO: Case updating, deleting Case Not Intersect(Target, databaseTable.ListColumns(DATABASE_SUBCAT_COLUMN_HEADER).DataBodyRange) Is Nothing ' TODO: Validate if adding, updating or deleting a sub category tableRow = Target.Row - databaseTable.HeaderRowRange.Row + 1 ' Case: Add a subcategory table AddTableInSheetByName databaseTable.ListColumns(DATABASE_MAINCAT_COLUMN_HEADER).Range(tableRow), Target.Value2, Target.Parent ' TODO: Case updating, deleting Case Else End Select
End Sub
Public Function AddSheetByTitle(ByVal Title As String, Optional ByVal ReturnSheet As Worksheet) As Worksheet
' TODO: Validate if sheet name is valid If SheetExists(Title) = True Then Exit Function Dim newWorksheet As Worksheet Set newWorksheet = ThisWorkbook.Worksheets.Add(after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)) ' Rename the new sheet newWorksheet.Name = Title ' Return to a previous sheet If Not ReturnSheet Is Nothing Then ReturnSheet.Activate Set AddSheetByTitle = newWorksheet
End Function
Public Function AddTableInSheetByName(ByVal TargetSheetName As String, ByVal TableName As String, Optional ByVal ReturnSheet As Worksheet) As ListObject
Dim targetSheet As Worksheet Dim targetTable As ListObject Dim lastRow As Long If SheetExists(TargetSheetName) = False Then Set targetSheet = AddSheetByTitle(TargetSheetName) End If If TableExists(TableName) = True Then Exit Function Set targetSheet = ThisWorkbook.Worksheets(TargetSheetName) lastRow = targetSheet.Cells(targetSheet.Rows.Count, 1).End(xlUp).Row Set targetTable = targetSheet.ListObjects.Add(SourceType:=xlSrcRange, Source:=targetSheet.Cells(lastRow, TABLE_COLUMN_LOCATION).Offset(TABLE_OFFSET_ROWS)) targetTable.Name = TableName ' Set table headers and content targetTable.HeaderRowRange.Cells(1).Value2 = TableName ' Return to a previous sheet If Not ReturnSheet Is Nothing Then ReturnSheet.Activate
End Function
Private Function SheetExists(ByVal SheetName As String) As Boolean
Dim evalSheet As WorksheetOn Error Resume Next Set evalSheet = ThisWorkbook.Sheets(SheetName) On Error GoTo 0 SheetExists = (Not evalSheet Is Nothing)
End Function
Private Function TableExists(ByVal TableName As String) As Boolean
Dim evalTable As ListObject
Dim evalName As String
' TODO: check if TableName is valid (search for invalid chars)
evalName = Replace(TableName, " ", "_")
On Error Resume Next
TableExists = (Range(evalName).ListObject.Name = TableName)
On Error GoTo 0
End Function
> Note: Your end result belongs to an specific type of table. My code
> adds (as you initially asked) a new table to the sheet. The alternative would be to copy (duplicate) a source table and rename it.
Hope this helps. Remember to mark the answer if it does.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论