【问题标题】:EXCEL VBA: Sort through years and find simple Average,Max,and Min by decadeEXCEL VBA:对年份进行排序并按十年查找简单的平均值、最大值和最小值
【发布时间】:2012-10-13 17:09:26
【问题描述】:

好的,场景如下:我目前正在处理三列。 A 列是我的唯一 ID,B 列是我的年份,C 列是我的价值。我正在使用 excel,并且有大约 350,000 行可以使用,所以问题/目标:

我正在尝试找到正确的代码,可以筛选这些年,并按十年为我提供 VALUE 列 C 的 AVERAGE、MAX 和 MIN 值。

同样,我有数十万行代码要处理,我想按从 1940 年代到 2010 年代的十年排序;每十年它会给我平均、最大值和最小值。

我只是一个业余程序员,所以我知道如何通过在漫长而乏味的时间段内创建多种排序来逐个十年地过滤它。但是,我想知道是否有人知道可以一举完成所有工作的代码,从而节省了程序必须多次筛选我的 350,000 行代码的过程。

我将非常感谢谁能教我这一点,祝你好运,谢谢!

编辑::(如何显示平均值、最大值和最小值))::

“啊,我很抱歉没有澄清这一点。我只是假设我会在它们“神奇地”出现后处理它,哈哈。无论如何,我将在一个简单的表格中显示我整理的十年信息在一个新的工作表中,其中 AVERAGE、MAX、MIN 将是三行标题,而十年将是表的列标题。"

【问题讨论】:

  • 结果应该在哪里?新的工作表?同一张工作表?您打算如何展示几十年?
  • 不用VBA也能做到这一点?你想要一个只有公式的解决方案吗?如果是这样,请告诉我您运行的是哪个版本的 XL。
  • 最好使用带有“按年分组”运算符和平均值、最大值、最小值的 SQL 语句来执行此操作。您可以将 Excel 工作表导入 Access 表并执行此操作。如果您熟悉 Access 和 SQL,我看到了另一个类似的问题,可能会给您一些想法:stackoverflow.com/questions/9226201/…
  • 我正在使用 XL2010。是的,我想你可以在没有 VBA 的情况下做到这一点,但我没有提到的背景是我实际上是如何使用一堆图表制作程序以及总共大约十几个其他信息列以及其他一些信息床单。但是,所有这些都需要在与此一样大的其他文件中多次完成,所以我正在制作一个宏来完成我需要的所有内容,这样我就可以在睡觉前运行它。我上面问的只是我试图完成的难题的另一部分。公式也会很好,我相信我可以适应 VBA :)

标签: vba sorting excel filter filtering


【解决方案1】:

我同意 Scott 的观点,即在大多数情况下,公式是比 VBA 更好的选择。但是您要求一些具体的事情,包括对数据进行排序,在单独的选项卡上显示结果,所以我假设在这种情况下您可以接受宏带来的额外开销。

您遗漏了有关数据的一些细节(数据类型、特定单元格位置等)...所以请参阅代码中的 cmets,您可能需要自定义。

我试图尽可能按字面意思回答您的问题...例如,我个人可能更喜欢表格中的结果而不是横着的结果,但这不是我接近答案的方式。

Sub SummarizeDecade()

Const YearColumn As Integer = 2  'assumes the first year is in cell B2
Const FirstDataRow As Integer = 2 'assumes the first year is in cell B2

Dim wb As Excel.Workbook, ws As Excel.Worksheet, wsNew As Excel.Worksheet
Dim rowStart As Long, rowEnd As Long, colPaste As Long
Dim decade As Integer
Dim avg As Double, mini As Double, maxi As Double 'you didn't specify data type, Double is most accommodating

   Set wb = ThisWorkbook
   Set ws = wb.ActiveSheet  'assumes you run the macro while the data sheet is the current sheet; would prefer to use a sheet name

   'setup new worksheet for summary results, as requested
   wb.Worksheets.Add
   Set wsNew = wb.Worksheets(1)
   wsNew.Name = "Results"
   wsNew.Cells(1, 1).Value = "Decade"
   wsNew.Cells(2, 1).Value = "Average"
   wsNew.Cells(3, 1).Value = "Minimum"
   wsNew.Cells(4, 1).Value = "Maximum"
   colPaste = 2

   ws.Activate
   ws.Cells(FirstDataRow, YearColumn).Sort ws.Cells(FirstDataRow, YearColumn), xlAscending, , , , , , xlYes 'sorts the data by year, as requested

   rowStart = FirstDataRow
   rowEnd = rowStart

   Do Until Len(ws.Cells(rowEnd, 3).Value) = 0 'be sure your data does not include strings with spaces, zeroes, etc.  Must be blank/null/empty.
      decade = Int(ws.Cells(rowStart, YearColumn) / 10) * 10

      Do Until Int(ws.Cells(rowEnd, YearColumn) / 10) * 10 <> decade
         rowEnd = rowEnd + 1
      Loop

      'calculate the average, max, and min
      avg = Application.WorksheetFunction.Average(ws.Range(ws.Cells(rowStart, 3), ws.Cells(rowEnd - 1, 3)))
      mini = Application.WorksheetFunction.min(ws.Range(ws.Cells(rowStart, 3), ws.Cells(rowEnd - 1, 3)))
      maxi = Application.WorksheetFunction.max(ws.Range(ws.Cells(rowStart, 3), ws.Cells(rowEnd - 1, 3)))

      'write the summaries on the new worksheet tab
      wsNew.Cells(1, colPaste).Value = decade
      wsNew.Cells(2, colPaste).Value = avg
      wsNew.Cells(3, colPaste).Value = mini
      wsNew.Cells(4, colPaste).Value = maxi

      colPaste = colPaste + 1
      rowStart = rowEnd
   Loop


End Sub

【讨论】:

  • 干杯!你真的在 ExactaBox 中一针见血。是的,我确实遗漏了一些信息,但是您构建了我可以添加和自定义的框架,我衷心感谢您,干得好!
  • 很高兴我能帮上忙...我是新来的,“接受”会很棒。谢谢。
【解决方案2】:

非 VBA 解决方案:

见下图。我冒昧地以简洁的格式设置数据以显示我的概念,但您可以轻松调整。相应地更改数据范围以及 Max / Min 公式。

请务必按Ctrl + Shift + Enter,因为这些公式是数组公式。

【讨论】:

  • 这是一条我可以根据自己的目的进行调整的路线,但不是我想要的,但我很感激帮助! ExactaBox 似乎在这个问题上一针见血。
猜你喜欢
  • 2020-03-01
  • 2021-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-16
  • 1970-01-01
  • 1970-01-01
  • 2016-12-29
相关资源
最近更新 更多