如何在Excel中将范围转换为单调列表

我有一个在Excel中看起来像这样的单元格的范围

Start End Cat 1 Cat 2 Value 2011 2015 1 1 2.09 2011 2015 1 2 1.71 2011 2015 2 1 0.66 2011 2015 2 2 2.07 2011 2015 3 1 0.66 2011 2015 3 2 2.07 2016 2020 1 1 3.72 2016 2020 1 2 2.22 2016 2020 2 1 1.38 2016 2020 2 2 2.34 2016 2020 3 1 1.38 2016 2020 3 2 2.34 ... 

因此,例如,第一行意味着对于2011-2015年的所有年份,值2.09对[category1 = 1][category2 = 1]是有效的(不考虑类别对于问题的意义)。

我想要的是扩大名单,看起来像这样

 Year Cat 1 Cat 2 Value 2011 1 1 2.09 2011 1 2 1.71 2011 2 1 0.66 2011 2 2 2.07 2011 3 1 0.66 2011 3 2 2.07 2012 1 1 2.09 2012 1 2 1.71 2012 2 1 0.66 2012 2 2 2.07 2012 3 1 0.66 2012 3 2 2.07 ... 

即复制第一范围(2011-2015)中每个值的类别1,类别2和值列,然后复制第二范围年份(2016-2020)的第二列列等等。

做这个的最好方式是什么? 是否有一些Excel公式欺骗,我可以申请或是写一些macros的最佳方式?

这是一个闪电般的不同的方法,并提供所需的输出:

 Sub MakeNewTable() Dim k As Long, i As Long, j As Long, r As Long Dim sh1 As Worksheet, sh2 As Worksheet Dim maxYear As Long, minYear As Long, nrow As Long Dim groups() As Double, myData As Variant Set sh1 = Sheets("Sheet1") Set sh2 = Sheets("Sheet2") myData = sh1.UsedRange '' Put your range here nrow = UBound(myData, 1) minYear = Application.WorksheetFunction.Min(Range(sh1.Cells(2, 1), sh1.Cells(nrow + 1, 1))) maxYear = Application.WorksheetFunction.Max(sh1.Range(sh1.Cells(2, 2), sh1.Cells(nrow + 1, 2))) ReDim groups(minYear To maxYear, 1 To 3, nrow) For i = nrow To 2 Step -1 For j = myData(i, 1) To myData(i, 2) For k = 1 To 3: groups(j, k, i) = myData(i, k + 2): Next k groups(j, 1, 1) = i '' Getting first time a value appears... Used in loop below If i > groups(j, 2, 1) Then groups(j, 2, 1) = i '' Getting last time a value appears Next j Next i k = 2 For i = minYear To maxYear For j = groups(i, 1, 1) To groups(i, 2, 1) If groups(i, 1, j) > 0 Then sh2.Cells(k, 1) = i For r = 1 To 3: sh2.Cells(k, r + 1) = groups(i, r, j): Next r k = k + 1 End If Next j Next i End Sub 

它利用存储和操作数组中的数据,所有繁重的工作都在本地完成。 我通过创build一个分组数组来保存数据,这个分组数组叫做groups ,它利用索引来快速组织数据。 应该指出的是,这个algorithm也是非常普遍的,也就是说,如果数据已经很好地按年分段,那并不重要。 例如,这个algorithm在表格上工作,如:

 Start End 2011 2015 ... 2008 2013 ... 2018 2021 ... 2011 2015 ... 1991 2003 ... 1998 2000 ... etc. 

如果你没有按照你列出的方式sorting(换句话说,每一行将扩展到该范围,然后移动到下一行),那么类似这样的东西就可以工作:

 Sub ExpandRanges() Dim ws1, ws2 As Worksheet Dim row1, row2, year As Integer Set ws1 = Sheets("Sheet2") Set ws2 = Sheets("Sheet3") row1 = 2 row2 = 2 While ws1.Cells(row1, 1).Value <> "" For year = ws1.Cells(row1, 1).Value2 To ws1.Cells(row1, 2).Value2 ws2.Cells(row2, 1).Value = year ws2.Range("B" & row2 & ":D" & row2).Value = ws1.Range("C" & row1 & ":E" & row1).Value row2 = row2 + 1 Next year row1 = row1 + 1 Wend End Sub 

如果你确实需要按年sorting,那么在这个结尾处快速sorting也可以实现。