根据单元格值将数据分成行

时间:2019-05-27 15:22:37

标签: excel vba powerquery

这是我第一次在这里道歉,如果我问错了。

我对excel有很好的理解,但是我只真正将它用于一些易于调整的公式。我试图找出从哪里开始的问题,但我什至不知道要寻找什么才能找到答案。根据我的发现-应该可以通过Power Query或Excel-VBA宏实现它吗?

我在一张纸上可能有400行数据。我需要根据4列中的值来分隔每一行数据。

这是我制作的屏幕截图,并提供了一个简短示例,以说明我要实现的目标。

enter image description here

屏幕截图的顶部是现在的数据。底部是我希望如何修改数据。将为产生的任何费用创建一个新行(每行的基本费用,然后,如果他们已经产生了定单费,则添加新行,如果产生了优先权费用,则添加新行,依此类推。 “ 0”,则无新行)。

如果有人对如何执行此操作有任何指导,那就太好了。我不是在寻求解决方案,而是在寻求一些有关我可以研究或应该学到的知识的提示,以实现类似的目标!

2 个答案:

答案 0 :(得分:0)

我很着急,所以赶紧执行此代码。如果需要的话可以回来解释一下。但这给了我您所显示的输出。

Option Explicit

Private Sub UnpivotColumns()

    Dim sourceSheet As Worksheet
    Set sourceSheet = ThisWorkbook.Worksheets("Sheet1")

    Dim lastSourceRow As Long
    lastSourceRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row

    Dim lastSourceColumn As Long
    lastSourceColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count).End(xlToLeft).Column

    Dim sourceData As Range
    Set sourceData = sourceSheet.Range("A2", sourceSheet.Cells(lastSourceRow, lastSourceColumn))

    Dim destinationSheet As Worksheet
    Set destinationSheet = ThisWorkbook.Worksheets("Sheet2")

    destinationSheet.Cells.Clear
    destinationSheet.Range("A1:D1").Value = Array("Name", "Description", "Currency", "Fee")

    Dim destinationRowIndex As Long
    destinationRowIndex = 1 ' Skip header row

    Dim outputArray(1 To 4) As Variant ' Re-use same array throughout procedure

    Dim sourceRowIndex As Long
    For sourceRowIndex = 2 To lastSourceRow

        ' Base fee always needs writing (unconditionally)
        outputArray(1) = sourceSheet.Cells(sourceRowIndex, "A") ' Name
        outputArray(2) = "Base Fee"  ' Description
        outputArray(3) = "USD" ' Currency
        outputArray(4) = 150 ' Fee amount

        destinationRowIndex = destinationRowIndex + 1
        destinationSheet.Cells(destinationRowIndex, "A").Resize(1, 4).Value = outputArray

        Const FIRST_COLUMN_TO_UNPIVOT As Long = 4 ' Skip first three columns

        Dim sourceColumnIndex As Long
        For sourceColumnIndex = FIRST_COLUMN_TO_UNPIVOT To lastSourceColumn Step 2
            outputArray(2) = sourceSheet.Cells(1, sourceColumnIndex)  ' Unpivoted description
            outputArray(3) = sourceSheet.Cells(sourceRowIndex, sourceColumnIndex + 1) ' Unpivoted currency
            outputArray(4) = sourceSheet.Cells(sourceRowIndex, sourceColumnIndex) ' Unpivoted fee amount

            ' Skip amount if nil/zero
            If outputArray(4) > 0 Then
                destinationRowIndex = destinationRowIndex + 1
                destinationSheet.Cells(destinationRowIndex, "A").Resize(1, 4).Value = outputArray
            End If

        Next sourceColumnIndex

    Next sourceRowIndex

End Sub

代码有一些假设(对于您的屏幕截图来说是正确的,但如果数据的布局发生变化,则可能不正确)。

此代码的错误之处:

  • 它是刚性的,不是很灵活/动态
  • 这会很慢,因为它一次只能读/写一个单元格。
  • 没有参照完整性(假定列索引/偏移量,并且从未实际检查/声明)。如果数据的布局/位置发生变化,这将成为一个问题。

此代码的好处:

  • 希望它能正常工作(例如您在屏幕快照中显示的示例)。

这是我的代码之前的数据(在Sheet1上):

Before

这是我的代码后面的数据(在Sheet2上):

After

此外,在Power Query中也同样可能发生这种情况(并且可能也用更少的代码行)。

答案 1 :(得分:0)

假设示例中的列标题(名称,电子邮件,订单日期,订单金额,货币,加急费,货币,快递费,货币)的源数据位于表头为Table1的命名范围内,则powerquery代码将在下面。

let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Added Custom" = Table.AddColumn(Source, "Base Fee", each "USD:150"),
#"Merged Columns" = Table.CombineColumns(Table.TransformColumnTypes(#"Added Custom", {{"Order Amount", type text}}, "en-US"),{"Currency", "Order Amount"},Combiner.CombineTextByDelimiter(":", QuoteStyle.None),"Order Amount1"),
#"Merged Columns1" = Table.CombineColumns(Table.TransformColumnTypes(#"Merged Columns", {{"Expedite Fee", type text}}, "en-US"),{"Currency2", "Expedite Fee"},Combiner.CombineTextByDelimiter(":", QuoteStyle.None),"Expedite Fee1"),
#"Merged Columns2" = Table.CombineColumns(Table.TransformColumnTypes(#"Merged Columns1", {{"Courier Fee", type text}}, "en-US"),{"Currency3", "Courier Fee"},Combiner.CombineTextByDelimiter(":", QuoteStyle.None),"Courier Fee1"),
#"Removed Other Columns" = Table.SelectColumns(#"Merged Columns2",{"Name", "Order Amount1", "Expedite Fee1", "Courier Fee1","Base Fee"}),
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Removed Other Columns", {"Name"}, "Description", "Value"),
#"Split Column by Delimiter" = Table.SplitColumn(#"Unpivoted Other Columns", "Value", Splitter.SplitTextByDelimiter(":", QuoteStyle.Csv), {"Currency", "Fee"}),
#"Replaced Value" = Table.ReplaceValue(#"Split Column by Delimiter","1","",Replacer.ReplaceText,{"Description"})
in #"Replaced Value"