将具有数据列的行转换为Excel 2007中具有多行的列

我有一行数据如下:

header1 header2 header3 header4 header5 row key datavalue1 datavalue2 datavalue3 datavalue4 datavalue5.... 

所以基本上,我有一个非规范化的数据集的数据值可能会或可能不会逐行为空。 我需要正常化他们。

 12345678 NULL 10 3 NULL 14 

会成为:

 12345678 header2 10 12345678 header3 3 12345678 header5 14 

我可以通过使用粘贴特殊转换来做到这一点,但我有成千上万的行,我需要确保我得到每个正确的行键。 此外,每一行都有一些与之相关的描述,我需要复制每个数据值。

什么是最简单的方法来转换每行的列,这样我有一个单列的所有非空数据值加上相关的数据值引用的多行? 我需要能够旋转数据集。

如果您有五个“标题”列,请input这些公式

 H1: =OFFSET($A$1,INT((ROW()-1)/5)+1,0) I1: =OFFSET($A$1,0,IF(MOD(ROW(),5)=0,5,MOD(ROW(),5))) J1: =INDEX($A$1:$F$9,MATCH(H1,$A$1:$A$9,FALSE),MATCH(I1,$A$1:$F$1,FALSE)) 

复制H1:J? 并在顶部粘贴特殊值。 对J列进行sorting并删除任何零。 如果数据中有合法的零,那么首先需要用一些唯一的stringreplace空白单元格,然后再删除。

如果你有更多的列,那么把上面所有的公式中的'5'换成你所拥有的任何数字。

在我看来,你想要做的一部分是“去枢轴”的数据透视表。 我发现这个技巧是非常有帮助的,当我不得不做类似的任务时: http : //spreadsheetpage.com/index.php/tip/creating_a_database_table_from_a_summary_table/

请注意,在Excel 2007中,可以使用按键Alt + D,P访问旧的Excel 2003数据透视表向导。

Excel有一个转置function,可以满足您的需求。 这是相当隐藏,有点笨拙,但可能比钻研VBA更容易。 以下是Excel 2007帮助摘录:

Blockquote开关(转置)列和行显示全部隐藏所有如果数据是以列或行的formsinput的,但是您希望将该数据重新排列成行或列,则可以快速将数据从一个转移到另一个。

例如,按照列组织的区域销售数据在转换数据后出现在行中,如下图所示。

1.在工作表上,执行以下操作:要将列中的数据重新排列为行,请select包含数据的列中的单元格。 要将数据从行重新排列到列,请select包含数据的行中的单元格。 2.在“主页”选项卡的“剪贴板”组中,单击“复制”。

键盘快捷键要复制选定的数据,也可以按CTRL + C。

注意您只能使用“复制”命令重新排列数据。 要成功完成此过程,请不要使用“剪切”命令。

3.在工作表上,select要重新排列复制数据的目标行或列的第一个单元格。 注意复制区域(复制区域:当您要将数据粘贴到其他位置时复制的单元格复制单元格后,会在其周围出现一个移动边框,表示它们已被复制)并粘贴区域(粘贴区域:使用Office剪贴板剪切或复制数据的目标目标)不能重叠。 请确保您select的粘贴区域中的单元格落在复制数据的区域之外。

4.在“开始”选项卡上的“剪贴板”组中,单击“粘贴”下方的箭头,然后单击“转置”。 5.数据转换成功后,可以删除复制区域的数据。 提示如果您转置的单元格包含公式,则将转置公式,并自动调整转置单元格中数据的单元格引用。 要确保公式继续正确地引用非转换单元格中的数据,请在转换它们之前使用公式中的绝对引用。

有关更多信息,请参阅在相对,绝对和混合引用之间切换。

大段引用

让我们来看看VBA中的一个可能的解决scheme。 我认为这真的会有所帮助。 这里有几件事你应该知道我的代码。

  • 您需要将此代码放入VBA中的代码模块(与macros相同的位置)
  • 看看我为什么命名表:原始和规范化。 你要么要改变你的工作表名称或代码
  • 我正在检查值为NULL的string字段。 如果单元格为空,则需要检查If IsEmpty(rngCurrent.Value) Then

 Sub NormalizeSheet() Dim wsOriginal As Worksheet Dim wsNormalized As Worksheet Dim strKey As String Dim clnHeader As Collection Dim lngColumnCounter As Long Dim lngRowCounterOriginal As Long Dim lngRowCounterNormalized As Long Dim rngCurrent As Range Dim varColumn As Variant Set wsOriginal = ThisWorkbook.Worksheets("Original") 'This is the name of your original worksheet' Set wsNormalized = ThisWorkbook.Worksheets("Normalized") 'This is the name of the new worksheet' Set clnHeader = New Collection wsNormalized.Cells.ClearContents 'This deletes the contents of the destination worksheet' lngColumnCounter = 2 lngRowCounterOriginal = 1 Set rngCurrent = wsOriginal.Cells(lngRowCounterOriginal, lngColumnCounter) ' We'll loop through just the headers to get a collection of header names' Do Until IsEmpty(rngCurrent.Value) clnHeader.Add rngCurrent.Value, CStr(lngColumnCounter) lngColumnCounter = lngColumnCounter + 1 Set rngCurrent = wsOriginal.Cells(lngRowCounterOriginal, lngColumnCounter) Loop 'Here we'll reset our Row Counter and loop through the entire data set' lngRowCounterOriginal = 2 lngRowCounterNormalized = 1 lngColumnCounter = 1 Do While Not IsEmpty(wsOriginal.Cells(lngRowCounterOriginal, lngColumnCounter)) Set rngCurrent = wsOriginal.Cells(lngRowCounterOriginal, lngColumnCounter) strKey = rngCurrent.Value ' Get the key value from the current cell' lngColumnCounter = 2 'This next loop parses the denormalized values for each row' Do While Not IsEmpty(wsOriginal.Cells(lngRowCounterOriginal, lngColumnCounter)) Set rngCurrent = wsOriginal.Cells(lngRowCounterOriginal, lngColumnCounter) 'We're going to check to see if the current value' 'is equal to NULL. If it is, we won't add it to' 'the Normalized Table.' If rngCurrent.Value = "NULL" Then 'Skip it' Else 'Add this item to the normalized sheet' wsNormalized.Range("A" & lngRowCounterNormalized).Value = strKey wsNormalized.Range("B" & lngRowCounterNormalized).Value = clnHeader(CStr(lngColumnCounter)) wsNormalized.Range("C" & lngRowCounterNormalized).Value = rngCurrent.Value lngRowCounterNormalized = lngRowCounterNormalized + 1 End If lngColumnCounter = lngColumnCounter + 1 Loop lngRowCounterOriginal = lngRowCounterOriginal + 1 lngColumnCounter = 1 'We reset the column counter here because we're on a new row' Loop End Sub 

我将创build一个VBAmacros循环每一行,并将数据输出到另一个页面。 一旦数据输出,这将允许您在新页面中创build数据透视表。

不知道你对VBA有多熟悉,但是通过将数据加载到一个数组(或者如果你真的想要正确地做对象的话),并把它写回去,这很容易做到。

这是一个很好的VBA文档的链接。

http://social.msdn.microsoft.com/Forums/en/isvvba/thread/d712dbdd-c876-4fe2-86d2-7d6323b4262c

编辑

请注意,这不是一个完全可行的解决scheme,而是一个真正的通用框架,可以帮助您朝着正确的方向发展。

作为一个通用的例子,你需要做很多事情(不是最好的方法,但可能是最简单的方法),像这样的东西应该让你开始,虽然很难说没有看到更多的工作表。

 Sub RowsToColumns () Application.ScreenUpdating = False Dim srcWrkSheet As Worksheet Dim destWrkSheet As Worksheet Dim excelData as pExcelData Dim srcRowNumber As Long Dim srcRolNumber As Long Dim destRowNumber As Long Dim destColNumber As Long SET srcWrkSheet = Sheets("YourSourceWorkSheetName") SET destWrkSheet = Sheets("YourDestinationWorkSheetName") srcRowNumber = 1 srcColNumber = 1 destRowNumber = 1 destColNumber = 1 'Loop until blank row is encountered in column 1 Do destWrkSheet.Cells(destRowNumber ,1).Value = "Header 1 " & srcWrkSheet.Cells(srcRowNumber,srcColNumber ) destWrkSheet.Cells(destRowNumber ,1).Value = "Header 2 " & srcWrkSheet.Cells(srcRowNumber ,srcColNumber) srcRowNumber = srcRowNumber + 1 srcColNumber = srcColNumber + 1 destRowNumber = destRowNumber + 1 Loop Until srcWrkSheet .Cells(rowNumber, 1).value = "" End Sub