【问题标题】:Split delimited field into Different rows将分隔字段拆分为不同的行
【发布时间】:2013-12-31 15:53:38
【问题描述】:

所以每天我都会收到一个带有订单的 Excel 工作表,它们看起来像这样:

Date        Vendor     OrderID/Quantity         Total 
12/28/2013  Nike       1111111-8;2222222-12     20
12/29/2013  Adidas     3333333-5;4444444-10     15
12/30/2013  Wrangler   5555555-3                3  

与我一起工作的大多数人都可以使用它,但对我来说却不行,因为我想将每个 OrderID 与数量分开来识别。 7 位数字之间的“-”用于将 ID 与其关联的单元数分开。但本质上,当我将此表导入访问时,我想创建另一个拆分这些值的表。

Date        Vendor     OrderID  Quantity        
12/28/2013  Nike       1111111  8               
12/28/2013  Nike       2222222  12              
12/29/2013  Adidas     3333333  5               
12/29/2013  Adidas     4444444  10              
12/30/2013  Wrangler   5555555  3 

这对我来说更有用,但使用两个定界符(“-”和“;”)生成是一项艰巨的任务。我对 VBA 没问题,但我正在努力寻找解决冲突的方法。那我该怎么做呢?

【问题讨论】:

  • 当您说“订单表”时,它是作为 Excel 电子表格出现的吗? SQL Server 表?文本文件?你怎么得到这张桌子?根据来源,您可能希望以不同的方式对其进行攻击,因此信息至关重要。
  • @JohnnyBones 抱歉,遗漏了这个细节,目前它以 Excel 表格的形式出现
  • 我最初打算根据您的回复建议设置 Excel 模板,但在查看 Blackhawk 的回答后,我认为它可能更容易、更可靠。而不是导入电子表格,您可以只链接它并针对链接的工作表运行 VBA。我对您的数据提取频率以及它们的命名方式并不肯定,但如果这是一个选项,那么这将为您节省一些额外的工作。

标签: sql ms-access vba


【解决方案1】:

我能想到的最直接的方法是 VBA Split 函数。请注意,我设置了 tblStaging 暂存表,其中所有字段都作为文本类型从 Excel 导入,但我将 tblOrders 表设置为(我假设是)正确的类型:日期为日期,供应商作为文本,OrderID 作为数字,数量作为数字。详情见代码中的cmets。

Public Sub SplitOrders()
    Dim rsStaging As Recordset
    Dim rsOrder As Recordset
    Dim arrOrders() As String
    Dim arrOrderDetails() As String

    'Rename these for whatever your tables are called'
    Set rsStaging = CurrentDb.OpenRecordset("tblStaging")
    Set rsOrder = CurrentDb.OpenRecordset("tblOrders")

    rsStaging.MoveFirst
    While Not rsStaging.EOF

        'Split into an array of Orders'
        arrOrders = Split(rsStaging.Fields("OrderID/Quantity"), ";")

        For i = 0 To UBound(arrOrders)

            'Split the OrderID and Quantity for each Order'
            arrOrderDetails = Split(arrOrders(i), "-")

            'Create the new record in tblOrders'
            With rsOrder
                .AddNew
                !Date = CDate(rsStaging!Date)
                !Vendor = rsStaging!Vendor
                !OrderID = CLng(arrOrderDetails(0)) 'If the OrderID can contain letters, symbols or leading zeros, omit the CLng( ... ) call'
                !Quantity = CLng(arrOrderDetails(1))
                .Update
            End With

        Next
        rsStaging.MoveNext
    Wend
End Sub

【讨论】:

  • 不错。数组成员都是字符串类型,所以他可能需要强制转换它们以匹配目标字段的数据类型,例如!OrderID = CLng(arrOrderDetails(0))
  • +1 用于考虑使用数组的 UBound 来确定循环大小。我完成了一个更复杂的解决方案,并认为这个解决方案更好。
【解决方案2】:

我希望将其分解为不同的部分,而不是尝试一次解析所有数据。例如,步骤 1 可能是将文件导入临时表(看起来像您问题中的第一个数据示例)。第 2 步是查询表以检测任何包含“;”的行(可能使用 InStr 函数或通配符搜索 like '*;*'。获取这些记录并将它们解析为两个或多个记录。第三,识别任何不包含 ';' 的记录并将它们解析为单个记录。所有结果 ( clean) 记录可以进入您的目标表进行进一步分析。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 2012-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多