假期中,接到业务一个Excel的求助电话,比较复杂,结合百度,经过一晚上的努力,幸不辱命。
还是看数据说话,有一个Excel数据表A,原型如下: 编码 名称 供应商
111 阿莫西林 公司AAA
111 阿莫西林 公司BBB
111 阿莫西林 公司CCC
222 达克宁 公司CCC
222 达克宁 公司BBB
333 康泰克 公司BBB
444 阿莫西林1 公司AAA
444 阿莫西林1 公司BBB
444 阿莫西林1 公司CCC
希望得到数据表B,处理结果如下:
编码 名称 供应商1 供应商2 供应商3 供应商4 ...
111 阿莫西林 公司AAA 公司BBB 公司CCC
222 达克宁 公司CCC 公司BBB 333 康泰克 公司BBB
444 阿莫西林1 公司AAA 公司BBB 公司CCC
很显然,这是一个转置问题,但是有两个问题:
1.原始表A中数据巨大,近十万行记录,而且由原始表-> 结果表的过程希望可以重复;
2.原始表中每一个编码的记录行数不确定。
总结起来就是 “不定行转置,或者分组转置”
解决方案:
首先想到的把原始表导入数据库,用sql实现;好处是快速,缺点是门槛太高,需要信息部门介入,所以用VBA是一个比较合理的方案,具体算法如下:
- Sub MySort()
- '取消筛选
- Workbooks(1).Activate
- If ActiveSheet.AutoFilterMode Then '如果 表2 当前为自动过滤状态
- Selection.AutoFilter '取消过滤
- End If
-
-
- '先排序
- Columns("A:O").Select
- Selection.Sort Key1:=Range("A1"), Order1:=xlAscending, Key2:=Range("C1") _
- , Order2:=xlAscending, Header:=xlGuess, OrderCustom:=1, MatchCase:= _
- False, Orientation:=xlTopToBottom, SortMethod:=xlPinYin, DataOption1:= _
- xlSortNormal, DataOption2:=xlSortNormal
-
-
- Dim RowCount, ColCount, FlagCol
- '取最大行数,excel2007 max rows =1048576,excel2003 max rows =65536
- 'RowCount = Selection.Rows.Count
- RowCount = Range("A1048576").End(xlUp).Row
- '取最大列数
- ColCount = Selection.Columns.Count
- '新增一列用来标记是否第一行
- FlagCol = ColCount + 1
- 'MsgBox "总行数" & RowCount & ",总列数" & ColCount & " " & ColCount + 1 & Cells(1, ColCount)
- '第一行是表头,第二行才是数据
- For i = 2 To RowCount
- j = 1
- Cells(i, ColCount + 1) = "1"
- Do While True
- If Cells(i, 1) = Cells(i + j, 1) Then
- Cells(i + j, FlagCol) = "0"
- ' 第3列是“转置”列
- Cells(i, FlagCol + j) = Cells(i + j, 3)
- Else
- i = i + j - 1
- Exit Do
- End If
- j = j + 1
- Loop
- Next
-
- Columns("A:S").Select
- Selection.AutoFilter
- ActiveSheet.Range("$A$1:$S" & RowCount).AutoFilter Field:=FlagCol, Criteria1:="1"
- End Sub
alimama_pid="mm_12187975_1642518_5895203"; alimama_titlecolor="0000FF"; alimama_descolor ="000000"; alimama_bgcolor="FFFFFF"; alimama_bordercolor="E6E6E6"; alimama_linkcolor="008000"; alimama_bottomcolor="FFFFFF"; alimama_anglesize="0"; alimama_bgpic="0"; alimama_icon="0"; alimama_sizecode="38"; alimama_width=290; alimama_height=200; alimama_type=2; |