在VBA中使用数组和macros

我是QA。 我不是一个开发人员,但是我问我的老板一些忙碌的工作。 她给了我一个开发项目,我完全糊涂了。 我们有一个电子表格,里面有很多销售人员和他们的客户。 对于每个客户,销售人员,客户姓名,销售额和地点如下所示:

Salesperson Customer Name Sales Amount Location salesperson1 customerA 3456789 Atlanta salesperson1 customerB 9475903 Atlanta salesperson1 customerC 7236433 Atlanta salesperson1 customerD 9809489 Raleigh salesperson2 customerA 3456789 Raleigh salesperson2 customerB 9475903 Raleigh salesperson2 customerC 7236433 Raleigh salesperson2 customerD 9809489 Raleigh salesperson2 customerE 3456789 Raleigh salesperson3 customerA 9475903 Portland salesperson3 customerB 7236433 Portland salesperson3 customerC 9809489 Portland salesperson4 customerA 9475903 Portland salesperson4 customerB 7236433 Portland salesperson4 customerC 9809489 Portland 

这个电子表格中有数百个销售人员和客户。 我的工作是创build一个新的工作簿模板。 我已经成功地做到了。 该模板获取相关的销售数据并根据销售数量进行计算。 目前,我已经能够将所有的数据从源代码获取到模板中,并且计算工作。 但是,我需要更进一步。 对于每个销售人员,我需要将数据加载到单独的工作表中,并且我需要为每个位置分别设置一个模板。 例如:请注意销售员3和销售人员4在波特兰的位置。 我需要在销售人员3的另一张表单上,并在同一个工作簿上为salesperson4分开一张表格,这个表格需要保存为PORTLAND.XLSM。 还需要一个名为RALEIGH.XLSM和ALTANTA.XLSM的模板。

所以这是我的问题:

  1. 当我从销售人员1到销售人员2到销售人员3到销售人员4时,如何创build数组?
  2. 我如何做一个arrays,将消除不在那个位置的人? 我认为我将需要一个工作表为每个位置,并且如果工作表的名称与该销售人员的位置不匹配,该销售人员不会在该工作簿中获取工作表。

我大约二十年前从大学gradle后就没有使用过VB。 我知道逻辑,但我不知道语言和语法。

正如Brad所说,这将是一个可以维持的野兽。 这就是说,如果我正确理解你的问题,我会使用.Range()函数。 如果你有你的数据在一个表中,你可以拉一个数组,并使用这个函数来做你想要的。

 Public Sub createSheets() Dim salespersons As Range, location As String, fileLocation As String, salesperson As String, newSheet As Worksheet Set salespersons = Range("Table1[Salesperson]") For i = 1 To salespersons.Count location = salespersons(i).Offset(0, 3).Value If i = 1 Or (salespersons(i).Offset(0, 3).Value <> salespersons(i - 1).Offset(0, 3).Value) Then Call createBook(location) End If Next i For Each wbook In Application.Workbooks For i = 1 To salespersons.Count If i = 1 Or (i > 1 And salespersons(i) <> salespersons(i - 1)) Then salesperson = salespersons(i).Value location = salespersons(i).Offset(0, 3).Value If location & ".xlsx" = wbook.Name Then If i = 1 Or (salespersons(i).Value <> salespersons(i - 1).Value) Then On Error Resume Next Set newSheet = wbook.Worksheets(salesperson) If Err.Number <> 0 Then Set newSheet = wbook.Worksheets.Add newSheet.Name = salesperson End If End If End If End If Next i Next End Sub Public Sub createBook(location As String) Dim newBook As Workbook, newSheet As Worksheet, result1 As Boolean, result2 As Boolean result1 = isWorkbookOpen(location & ".xlsx") If result1 = False Then On Error Resume Next Workbooks(location).Save If Err.Number <> 0 Then On Error Resume Next Workbooks.Open (location & ".xlsx") If Err.Number <> 0 Then Workbooks.Add.SaveAs (location & ".xlsx") Error Err.Number End If End If End If End Sub Function isWorkbookOpen(location As String) Dim ff As Long, Errno As Long On Error Resume Next ff = FreeFile() Open Filename For Input Lock Read As #ff Close ff Errno = Err On Error GoTo 0 Select Case Errno Case 0: isWorkbookOpen = False Case 70: isWorkbookOpen = True Case 75: isWorkbookOpen = False Case Else: Error Errno End Select End Function 

这是一个使用数据透视表的选项,需要NO VBA。 如果你使用这个,维护需要更多的工作,但是设置和切换非常简单:

  1. 从你的来源,做一个数据透视表,并将其添加到一个新的文档。
  2. 对于您的报表filter ,请添加SalesPersonLocation 。 现在将(All)的实际下拉列表保留,或者随机选取值。
  3. 对于您的行标签 ,您可以添加客户
  4. 对于你的价值观 ,你可以总结你的销售额。
  5. 让标签尽可能漂亮,如你所愿。 这将是所有销售人员的模板。 “ 选项”function区允许您添加自定义计算,行总数的百分比等。 你现在有一个标签,可以作为每个销售人员的模板!
  6. 为每个位置制作一个空白工作簿。 对于每个位置的工作簿,为每个在其中工作的销售人员添加此模板选项卡。 在该选项卡的数据透视表filter中,select位置和销售人员。
  7. 重复#6,直到每个工作簿都有一个每个销售人员的选项卡,每个选项卡都select了正确的销售人员和位置。

是的,这是单调的,但现在你已经完成了困难的一部分! 每个销售人员都有自己的选项卡,每个地点都有自己的文件。 由于您刚才制作的许多选项卡中的报告filter,每个选项卡都会被过滤为该销售人员在该位置的销售。

更新数据:

这个选项最大的缺点是,每当一个SalesPerson开始在一个新的位置销售,或者一个新的SalesPerson被雇用,你将不得不添加一个新的标签。 但是,由于您的常用模板选项卡,这不是很痛苦。

对于定期更新,只需打开每个文件并转到数据function区并全部刷新

这将在源表单(活动工作表)上循环,并生成许多工作簿(每个位置一个)。 包含每个销售人员的客户名称和销售额的工作表将添加到工作簿中。

一旦生成工作簿,将其保存为其位置的名称。

 ' get a named worksheet from specified workbook, creating it if required Public Function GetSheet(ByVal Name As String, ByVal Book As Workbook, Optional ByVal Ignore As Boolean = False) As Worksheet Dim Sheet As Worksheet Dim Key As String Dim Result As Worksheet: Set Result = Nothing Key = UCase(Name) ' loop over all the worksheets For Each Sheet In Book.Worksheets ' break out of the loop if the sheet is found If UCase(Sheet.Name) = Key Then Set Result = Sheet Exit For End If Next Sheet ' if the sheet isn't found.. If Result Is Nothing Then If Ignore = False Then If Not GetSheet("Sheet1", Book, True) Is Nothing Then ' rename sheet1 Set Result = Book.Worksheets("Sheet1") Result.Name = Name End If Else ' create a new sheet Set Result = Book.Worksheets.Add Result.Name = Name End If End If Set GetSheet = Result End Function Sub Main() Dim Source As Worksheet Dim Location As Workbook Dim Sales As Worksheet Dim LocationKey As String Dim SalesKey As String Dim Index As Variant Dim Map As Object: Set Map = CreateObject("Scripting.Dictionary") Dim Row As Long Set Source = ThisWorkbook.ActiveSheet Row = 2 ' Skip header row Do ' break out of the loop - assumes that the first empty row signifies the end If Source.Cells(Row, 1).Value2 = "" Then Exit Do End If LocationKey = Source.Cells(Row, 4).Value2 ' look at the location, and find the workbook, creating it if required If Map.Exists(LocationKey) Then Set Location = Map(LocationKey) Else Set Location = Application.Workbooks.Add(xlWBATWorksheet) Map.Add LocationKey, Location End If SalesKey = Source.Cells(Row, 1).Value2 ' get the sheet for the salesperson Set Sales = GetSheet(SalesKey, Location) ' insert a blank row at row 1 Sales.Rows(1).Insert xlShiftDown ' populate said row with the data from the source Sales.Cells(1, 1).Value2 = Source.Cells(Row, 2) Sales.Cells(1, 2).Value2 = Source.Cells(Row, 3) 'increment the loop Row = Row + 1 Loop ' loop over the resulting workbooks and save them - using the location name as file name For Each Index In Map.Keys Set Location = Map(Index) Location.SaveAs Filename:=Index Next Index End Sub 

更新

如果您正在生成只读报告,此代码才真正有用,每次生成报告时都会进行replace。 (这段代码可能无法在后续运行中保存,因为它不会检查文件是否存在,所以在运行之前需要先删除之前的文件)。

此代码(以其当前forms)需要与源数据一起添加到工作簿中,并且在运行Main()macros之前,数据表需要处于活动状态。

如果你正在努力做的不仅仅是生成一个报告(比如用你的新文件replace源数据表),那么在Access中会比较简单,正如一些人已经build议的那样。