Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matlab 合并具有连接日期的行_Matlab_Excel_Excel Formula_Vba - Fatal编程技术网

Matlab 合并具有连接日期的行

Matlab 合并具有连接日期的行,matlab,excel,excel-formula,vba,Matlab,Excel,Excel Formula,Vba,我有一个很大的Excel表格,上面有客户和订阅数据。从这个表中,我想合并具有连接停止和开始日期的记录/行,并在新的工作表中显示结果。数据的简化版本如下所示 Customer_id subscription_id start_date stop_date 1034 RV4 30-4-2012 30-1-2015 1035 AB7 30-1-2014 30-3-2014 1035

我有一个很大的Excel表格,上面有客户和订阅数据。从这个表中,我想合并具有连接停止和开始日期的记录/行,并在新的工作表中显示结果。数据的简化版本如下所示

Customer_id subscription_id   start_date    stop_date
1034        RV4               30-4-2012     30-1-2015
1035        AB7               30-1-2014     30-3-2014
1035        AB6               30-1-2014     30-3-2014
1035        AB7               30-12-2013    30-1-2014
1035        AB7               12-12-2012    30-12-2013
1035        AB7               12-9-2010     14-1-2011
因此,公式必须检查客户id和订阅id。当工作表中的两行或多行之间存在匹配且其中一行的停止日期与另一行的开始日期重叠时,则在提取和合并之后,一个新行必须显示第一行的开始日期和另一行的停止日期。如果有多行具有连接日期,这也必须起作用。提取后,与这些条件不匹配的所有行保持不变。所以结果是这样的:

Customer_id subscription_id start_date  stop_date
1034        RV4             30-4-2012   30-1-2015
1035        AB6             30-1-2014   30-3-2014
1035        AB7             12-12-2012  30-3-2014
1035        AB7             12-9-2010   14-1-2011
动态解决方案将是理想的,而新数据将添加到原始工作表中。虽然我知道,当您确定要查找的行始终位于彼此的下方时,这是可能的,但这里的情况并非如此,它不会为您提供非常动态的解决方案

所以我想Excel中需要某种数组函数,但在搜索了很多之后,我找不到合适的解决方案。我也有MATLAB可用,但对于这样的问题,我不知道从哪里开始。动态解决方案可能是可行的,但如果数据集太大,可能会让事情陷入困境,因为每次更改单元格时都需要它运行

基本上,我所能看到的实现这一点的最佳方法是创建出客户id和订阅id的唯一键,然后收集该键下的所有日期范围并合并它们

类似的内容应该可以让您开始(需要参考Microsoft脚本运行时):

Public子链接subscriptiondates()
Dim数据作为字典,源作为工作表,目标作为工作表
设置source=ActiveSheet
Set data=GetSubscriptions(源)
设置目标=source.Parent.Worksheets.Add
'复制标题
target.Range(target.Cells(1,1),target.Cells(1,4))。值=_
source.Range(source.Cells(1,1),source.Cells(1,4)).Value
暗排一样长
行=2
变光键作为变型,项目作为变型
对于数据中的每个键。键
对于数据中的每个项目(键)
target.Cells(第1行)=拆分(键“|”)(0)
target.Cells(第2行)=拆分(键“|”)(1)
target.Cells(第3行)=拆分(项目“|”)(0)
target.Cells(第4行)=拆分(第1项)
行=行+1
下一项
下一键
端接头
专用函数GetSubscriptions(源为工作表)作为字典
Dim订阅作为字典
Set subscribps=新字典
暗排一样长
Dim cust为字符串,SUB为字符串,起始为字符串,结束为字符串
'将所有数据收集为成对的客户|订阅,开始|结束
对于行=2到source.UsedRange.Rows.Count
Dim dates()作为字符串
cust=源.Cells(第1行).Value
subs=源.Cells(第2行).Value
'有效客户/订阅?
如果cust vbNullString和SUB vbNullString,则
起始=源.Cells(第3行).Value
结束=源.Cells(第4行).Value
'是否有结束和开始日期?
如果启动vbNullString并结束vbNullString,则
将键变暗为字符串
key=cust&“|”和subs
“新组合?
如果不存在subscribps.Exists(键),则
订阅。添加密钥,新集合
订阅(键)。添加开始和结束
其他的
订阅(键)。添加开始和结束
设置订阅(键)=合并日期(订阅(键))
如果结束
如果结束
如果结束
下一排
设置GetSubscriptions=subscripts
端函数
私有函数将日期(日期作为集合)合并为集合
变暗候选长度,索引长度
Dim values()作为字符串,test()作为字符串
Dim合并为布尔值
对于索引=1到日期。计数
值=拆分(日期(索引),“|”)
'检查它是否可以与任何其他行合并。
对于候选人=索引+1到日期。计数
测试=拆分(日期(候选人),“|”)
如果CDate(测试(0))>=CDate(值(0))和_
CDate(测试(0))=CDate(值(0))和_

CDate(测试(1))似乎您的结果包含一个错误:应该是2012年12月12日,而不是2013年12月12日。很好,我纠正了错误。我认为最好使用宏。这就是我将vba添加到您的标签的原因。谢谢,这已经非常接近我想要的了。但是,新工作表中的数据不正确。执行了合并,但结果不正确,我看不出是什么原因造成的。根据上面的示例数据,运行此脚本后最后一行消失,其他日期不正确。我怀疑这是由脚本中的一个小错误引起的,但我无法识别它。@itsme86-oops。太快了。错过了一些日期转换,并假设数据已排序。试试编辑。这很有魅力。除了我在这里显示的4列数据外,还有更多的列包含数据,但我可以(希望)自己将这些数据插入新创建的行中。@itsme86-创建字典时,您总是可以将它们附加到保存日期的管道分隔字符串的末尾。没有任何证据表明前两个元素是唯一使用的元素。很高兴能帮上忙。我刚刚发现一个奇怪的错误,我在工作表中的原始日期是日-月-年格式,通常返回月-日-年格式。例如,我的原始工作表中的11-1-2013在结果中返回为2013年11月1日,而不是2013年1月11日。我看不出这是由脚本还是计算机上的设置引起的。你知道如何纠正这个错误吗?I c
Public Sub LinkSubscriptionDates()

    Dim data As Dictionary, source As Worksheet, target As Worksheet

    Set source = ActiveSheet
    Set data = GetSubscriptions(source)
    Set target = source.Parent.Worksheets.Add

    'Copy headers
    target.Range(target.Cells(1, 1), target.Cells(1, 4)).Value = _
           source.Range(source.Cells(1, 1), source.Cells(1, 4)).Value

    Dim row As Long
    row = 2

    Dim key As Variant, item As Variant
    For Each key In data.Keys
        For Each item In data(key)
            target.Cells(row, 1) = Split(key, "|")(0)
            target.Cells(row, 2) = Split(key, "|")(1)
            target.Cells(row, 3) = Split(item, "|")(0)
            target.Cells(row, 4) = Split(item, "|")(1)
            row = row + 1
        Next item
    Next key

End Sub

Private Function GetSubscriptions(source As Worksheet) As Dictionary

    Dim subscrips As Dictionary
    Set subscrips = New Dictionary

    Dim row As Long
    Dim cust As String, subs As String, starting As String, ending As String

    'Gather all the data as pairs of customer|subscription, starting|ending
    For row = 2 To source.UsedRange.Rows.Count
        Dim dates() As String
        cust = source.Cells(row, 1).Value
        subs = source.Cells(row, 2).Value
        'Valid customer/subscription?
        If cust <> vbNullString And subs <> vbNullString Then
            starting = source.Cells(row, 3).Value
            ending = source.Cells(row, 4).Value
            'Has an ending and starting date?
            If starting <> vbNullString And ending <> vbNullString Then
                Dim key As String
                key = cust & "|" & subs
                'New combo?
                If Not subscrips.Exists(key) Then
                    subscrips.Add key, New Collection
                    subscrips(key).Add starting & "|" & ending
                Else
                    subscrips(key).Add starting & "|" & ending
                    Set subscrips(key) = MergeDates(subscrips(key))
                End If
            End If
        End If
    Next row

    Set GetSubscriptions = subscrips

End Function

Private Function MergeDates(dates As Collection) As Collection

    Dim candidate As Long, index As Long
    Dim values() As String, test() As String
    Dim merge As Boolean

    For index = 1 To dates.Count
        values = Split(dates(index), "|")
        'Check to see if it can be merged with any other row.
        For candidate = index + 1 To dates.Count
            test = Split(dates(candidate), "|")
            If CDate(test(0)) >= CDate(values(0)) And _
               CDate(test(0)) <= CDate(values(1)) Or _
               CDate(test(1)) >= CDate(values(0)) And _
               CDate(test(1)) <= CDate(values(1)) Then
                dates.Remove candidate
                merge = True
                Exit For
            End If
        Next candidate
        If merge Then Exit For
    Next index

    If merge Then
        'Pull both rows out of the collection.
        dates.Remove index
        values(0) = IIf(CDate(test(0)) < CDate(values(0)), _
                        CDate(test(0)), CDate(values(0)))
        values(1) = IIf(CDate(test(1)) > CDate(values(1)), _
                        CDate(test(1)), CDate(values(1)))
        'Put the merged date range back in.
        dates.Add values(0) & "|" & values(1)
        'Recurse.
        Set MergeDates = MergeDates(dates)
    End If

    Set MergeDates = dates

End Function