转置列

我有一个CSV文件,看起来像这样:

name, a v1, 1 name, b v1, 1 v2, 5 name, c v1, 4 v2, 6 name, d v2, 8 v3, asdf 

使用Excel或LibreOffice,我怎样才能将其转换为:

 name, v1, v2, v3 a, 1, , b, 1, 5, c, 4, 6, d, , 8, asdf 

我一直在寻找关键字转置,但它似乎不是正确的关键字来search – 所有的指南只显示如何做一个完整的转置,这是不是我想要的。

我也发现这个问题,但它假定非常干净的数据,必须手动调整的列数: Excel中的特定移调

我不知道列的数量,有些单元格可能会丢失。

我的公式为基础的方法与以下数据布局:

在这里输入图像描述

AB从CSV文件导入。

助手C列中的公式:

 =IF(A2="name",B2,C1) 

F1F2公式计算AC列中的唯一条目,不需要创build输出表(这两个数组公式都用Ctrl + Shift + Enter ):

 =SUM(1/COUNTIF(C2:C12,C2:C12)) =SUM(1/COUNTIF(A2:A12,A2:A12)) 

行标题 – C列中的唯一值( E6 ,使用Ctrl + Shift + Enter并拖放)

 =IFERROR(INDEX($C$2:$C$12, MATCH(0, COUNTIF($E$5:E5, $C$2:$C$12), 0)),"") 

Colummn标题 – A列中的唯一值( F5Ctrl + Shift + Enter ,然后向右拖动)

 =IFERROR(INDEX($A$2:$A$12, MATCH(0, COUNTIF($E$5:E5, $A$2:$A$12), 0)),"") 

两列INDEX / MATCH组合填充输出表( F6 ,用Ctrl + Shift + Enter ,并向右下拖动):

 =IFERROR(INDEX($B$2:$B$12,MATCH(F$5&$E6,$A$2:$A$12&$C$2:$C$12,0)),"") 

您需要执行两个操作来实现您的目标:

1.整理你的数据

将不同的数据types移动到单独的列。 你将有三个新的公式列:

  • 名称: =IF(A2="name",B2,C1)
  • V: =IF(A2="name","",A2)
  • 值: =IF(A2="name","",B2)

在这里输入图像说明

2.创build数据透视表

在这里你不能使用标准数据透视表,因为数值也可以是文本,有几个教程来创build它:

  • 来自Rober Ilbrink在Stackoverflow上与VBA的回答
  • 另一个来自clearlyandsimply.com与VBA的解决scheme

我从字面上理解了你的要求。 由于您想使用Excel来将CSV文件从第一个示例看起来像转换为第二个示例,所以我使用Excel VBA来:

  • 打开原始的CSV文件
  • 逐行阅读,并build立一个由每个name的项目组成的对象
  • 在结果数组中插入标签线
  • 重新构build由NameV's组成的Name
  • 用您要求的格式将行写入新的CSV文件。

如果您在记事本中打开CSV文件,您可以看到结果。

请务必设置对Windows脚本运行时的引用来访问FileSystemObject。


 Option Explicit 'SET REFERENCE to Windows Scripting Runtime ' Under Tools/References in the main menu above Sub ChangeCSV() Dim FSO As FileSystemObject, F As File, TS As TextStream Dim FN As String Dim V As Variant Dim S As String Dim vRes() As Variant Dim cI As cItem, colI As Collection Dim bFirstName As Boolean Dim I As Long, J As Long bFirstName = True 'Get File FN = Application.GetOpenFilename("CSV Files (*.csv), *.csv") 'Read file into textstream Set FSO = New FileSystemObject Set TS = FSO.OpenTextFile(FN, ForReading) Set colI = New Collection Do Until TS.AtEndOfStream S = TS.ReadLine 'Remove leading and trailing quote marks, if present 'If Left(S, 1) = """" Then S = Mid(S, 2) 'If Right(S, 1) = """" Then S = Left(S, Len(S) - 1) If Not S = "" Then 'skip empty lines V = Split(S, ",") If Trim(V(0)) = "name" Then If bFirstName = False Then colI.Add cI 'don't add if first name bFirstName = False Set cI = New cItem End If CallByName cI, CStr(Trim(V(0))), VbLet, Trim(V(1)) End If Loop colI.Add cI 'Compile results ReDim vRes(0 To colI.Count, 1 To 4) vRes(0, 1) = "Name" vRes(0, 2) = "V1" vRes(0, 3) = "V2" vRes(0, 4) = "V3" For I = 1 To colI.Count With colI(I) vRes(I, 1) = .Name vRes(I, 2) = .V1 vRes(I, 3) = .V2 vRes(I, 4) = .V3 End With Next I 'Note different file name Set TS = FSO.CreateTextFile(Left(FN, Len(FN) - 4) & "MOD.csv", True) For I = 0 To UBound(vRes) V = Empty ReDim V(1 To 4) For J = 1 To 4 V(J) = vRes(I, J) Next J TS.WriteLine Join(V, ",") Next I TS.Close Set FSO = Nothing End Sub