如何填充表中不符合特定条件的数据?

huangapple go评论68阅读模式
英文:

How to populate data that don't match specific criteria in table?

问题

I have 2 tabs, 1 Summary tab and the other 1 is Data tab. The summary tab contains a table with specific customer numbers(as shown in the summary table below).

我有两个选项卡,一个是汇总选项卡,另一个是数据选项卡。汇总选项卡包含一个具有特定客户号码的表格(如下所示)。

I'm trying to achieve the same set of data and columns that are listed in the summary table but for the rest of the customer numbers that do not exist in the summary table and insert them in a listbox.

我试图实现与汇总表中列出的相同的数据和列,但对于汇总表中不存在的其余客户号码,并将它们插入到一个列表框中。

Can anyone help me please with that?

有人能帮助我吗?

Thank you!

谢谢!

My Summary Table:

我的汇总表格:

Customer Number Customer Name aged debt Count of invoices Value
55850 ABC 1-30 2 2516
55850 ABC 30-60 1 52635
55850 ABC 60-90 1 102754
55850 ABC 90-120 1 152873
55850 ABC 120-180 1 202992
32336 DEF 30-60 2 253111
32336 DEF 60-90 2 303230
30131 GHI 1-30 1 353349
30131 GHI 30-60 2 403468
30131 GHI 60-120 2 453587
13914 JKL 1-30 2 503706
13914 JKL 30-60 2 553825
13914 JKL 60-90 2 603944
13914 JKL 90-120 1 654063

我的汇总表格:

客户号码 客户名称 逾期债务 发票数 价值
55850 ABC 1-30 2 2516
55850 ABC 30-60 1 52635
55850 ABC 60-90 1 102754
55850 ABC 90-120 1 152873
55850 ABC 120-180 1 202992
32336 DEF 30-60 2 253111
32336 DEF 60-90 2 303230
30131 GHI 1-30 1 353349
30131 GHI 30-60 2 403468
30131 GHI 60-120 2 453587
13914 JKL 1-30 2 503706
13914 JKL 30-60 2 553825
13914 JKL 60-90 2 603944
13914 JKL 90-120 1 654063

My Data source

我的数据源

Customer Number Customer Name Invoice Number Invoice Date Flag aged debt Value area
55850 ABC 121 01/01/2022 Yes 1-30 1258 ES
55850 ABC 122 02/01/2022 Yes 1-30 1258 WE
55850 ABC 123 03/01/2022 Yes 30-60 52635 NO
55850 ABC 124 04/01/2022 No 60-90 102754 SO
55850 ABC 125 05/01/2022 Yes 90-120 152873 ES
55850 ABC 126 06/01/2022 Yes 120-180 202992 WE
32336 DEF 127 07/01/2022 No 30-60 126555.5 NO
32336 DEF 128 08/01/2022 Yes 30-60 126555.5 SO
32336 DEF 129 09/01/2022 Yes 60-90 151615 ES
32336 DEF 130 10/01/2022 No 60-90 151615 WE
30131 GHI 131 11/01/2022 Yes 1-30 353349 NO
英文:

I have 2 tabs, 1 Summary tab and the other 1 is Data tab. The summary tab contains a table with specific customer numbers(as shown in the summary table below).

I'm trying to achieve the same set of data and columns that are listed in the summary table but for the rest of the customer numbers that do not exist in the summary table and insert them in a listbox.

can anyone help me please with that?

Thank you!

My Summary Table:

Customer Number Customer Name aged debt Count of invoices Value
55850 ABC 1-30 2 2516
55850 ABC 30-60 1 52635
55850 ABC 60-90 1 102754
55850 ABC 90-120 1 152873
55850 ABC 120-180 1 202992
32336 DEF 30-60 2 253111
32336 DEF 60-90 2 303230
30131 GHI 1-30 1 353349
30131 GHI 30-60 2 403468
30131 GHI 60-120 2 453587
13914 JKL 1-30 2 503706
13914 JKL 30-60 2 553825
13914 JKL 60-90 2 603944
13914 JKL 90-120 1 654063

My Data source

Customer Number Customer Name Invoice Number Invoice Date Flag aged debt Value area
55850 ABC 121 01/01/2022 Yes 1-30 1258 ES
55850 ABC 122 02/01/2022 Yes 1-30 1258 WE
55850 ABC 123 03/01/2022 Yes 30-60 52635 NO
55850 ABC 124 04/01/2022 No 60-90 102754 SO
55850 ABC 125 05/01/2022 Yes 90-120 152873 ES
55850 ABC 126 06/01/2022 Yes 120-180 202992 WE
32336 DEF 127 07/01/2022 No 30-60 126555.5 NO
32336 DEF 128 08/01/2022 Yes 30-60 126555.5 SO
32336 DEF 129 09/01/2022 Yes 60-90 151615 ES
32336 DEF 130 10/01/2022 No 60-90 151615 WE
30131 GHI 131 11/01/2022 Yes 1-30 353349 NO
30131 GHI 132 12/01/2022 Yes 30-60 201734 SO
30131 GHI 133 13/01/2022 No 30-60 201734 ES
30131 GHI 134 14/01/2022 No 60-120 226793.5 WE
30131 GHI 135 15/01/2022 Yes 60-120 226793.5 NO
13914 JKL 136 16/01/2022 Yes 1-30 251853 SO
13914 JKL 137 17/01/2022 Yes 1-30 251853 ES
13914 JKL 138 18/01/2022 Yes 30-60 276912.5 WE
13914 JKL 139 19/01/2022 Yes 30-60 276912.5 NO
13914 JKL 140 20/01/2022 Yes 60-90 301972 SO
13914 JKL 141 21/01/2022 Yes 60-90 301972 ES
13914 JKL 142 22/01/2022 Yes 90-120 654063 WE
13900 LMN 143 23/01/2022 No 1-30 120000 NO
13900 LMN 144 24/01/2022 Yes 30-60 180000 SO
13900 LMN 145 25/01/2022 Yes 60-90 50000 ES
13900 LMN 146 26/01/2022 No 90-120 60000 WE
13900 LMN 147 27/01/2022 Yes 120-180 70000 NO
13901 OOO 148 28/01/2022 Yes 30-60 3000 SO
13901 OOO 149 29/01/2022 No 60-90 40000 ES
13901 OOO 150 30/01/2022 No 90-120 50000 WE
13901 OOO 151 31/01/2022 No 120-180 60000 NO
13902 OOX 152 01/02/2022 No 30-60 10000 SO
13902 OOX 153 02/02/2022 No 60-90 20000 ES
13902 OOX 154 03/02/2022 Yes 90-120 30000 WE
13902 OOX 155 04/02/2022 Yes 120-180 40000 NO
 Option Explicit
                
                Sub test()
                Dim conn, rs As Object, sq As String, Accounts As String
                
                Set conn = CreateObject("ADODB.Connection")
                  With conn
                    .Provider = "Microsoft.ACE.OLEDB.12.0"
                    .ConnectionString = "Data Source=" & 
                      ThisWorkbook.FullName & ";" & _
                    "Extended Properties=""Excel 12.0 
                           Xml;HDR=Yes;IMEX=1"";"
                    .Open
                      End With
                       
                           sq = "SELECT T1.[Customer Number],T1. 
                                [Customer Name],T1.[Aged Debt] " & _      
                "COUNT(T1.[Invoice Number]) as [count of Invoices] " & _ 
                                "sum(T1.[Value]) as [values] " & _
                                "FROM[Data$] T1 " & _
    "WHERE T1.[Customer Number] Not In (" & Getcust(Accounts) & ") " & _
     "GROUP BY T1.[Customer Number],T1.[Customer Name],T1.[Aged Debt]"
                                        
             Set rs = conn.Execute(sq)
                                           
              If Not rs.EOF Then
               With Me.listbox1
                .Value = ""
               .Column = rs.GetRows
              .ColumnCount = rs.Fields.Count
              .ColumnHeads = False
             .ColumnWidths = "90,90,50,50,180"
                                        End With
                                       End If
                                       
                         rs.Close
                         conn.Close
                       Set rs = npthing
                       Set conn = Nothing
                       
                       
                       End Sub
                
   

     Public Function Getcust(Accounts As String) As String
       Dim dU1 As Object, cU1 As Variant, iU1 As Long, i As Integer
                        Set dU1 = CreateObject("Scripting.Dictionary")
               cU1 = Sheets("Summary").ListObjects(1).ListColumns("Customer 
                      Number").DataBodyRange
                        For iU1 = 1 To UBound(cU1, 1)
                            dU1(cU1(iU1, 1)) = 1
                        Next iU1
                              Accounts = "'"
                        For i = 0 To dU1.Count - 1
                           Accounts = Accounts & dU1.Keys()(i) & "','"
                        Next
                          Accounts = Left(Accounts, Len(Accounts) - 5)
                          Getcust = Accounts
                          
    End Function

答案1

得分: 0

Here are the translated parts of your code:

Write two Connection Only Power queries to read your Summary Data and your Datasource
Then Merge those queries using a LeftAnti join to get only the rows in data source that do not exist in the summary.
You can then use Transform, Group By to get the details you need for your summary e.g.

let
    Source = Table.NestedJoin(DataSource, {"Customer Number"}, Summary, {"Customer Number"}, "Summary", JoinKind.LeftAnti),
    #"Grouped Rows" = Table.Group(Source, {"Customer Number", "Customer Name", "aged debt"}, {{"Count of invoices", each Table.RowCount(_), Int64.Type}, {"Value", each List.Sum([Value]), type nullable number}})
in
    #"Grouped Rows"

Please note that I've left the code in its original format and haven't translated the actual Power Query code.

英文:

Write two Connection Only Power queries to read your Summary Data and your Datasource
Then Merge those queries using a LeftAnti join to get only the rows in data source that do not exist in the summary.
You can then use Transform, Group By to get the details you need for your summary e.g.

let
    Source = Table.NestedJoin(DataSource, {"Customer Number"}, Summary, {"ustomer Number"}, "Summary", JoinKind.LeftAnti),
    #"Grouped Rows" = Table.Group(Source, {"Customer Number", "Customer Name", "aged debt"}, {{"Count of invoices", each Table.RowCount(_), Int64.Type}, {"Value", each List.Sum([Value]), type nullable number}})
in
    #"Grouped Rows"

答案2

得分: 0

请使用标准的方式。您必须从真正存在的地方(工作表)设置lisObjects(表格)。活动工作表必须包含一个名为 "ListBox1" 的 ActiveX 列表框:

Sub LoadListBoxWithNotExistingCustomNo()
   Dim tbl1 As ListObject, tbl2 As ListObject, arrT1, arrT2, arrUnique, mtch, arrIt, arFin
   Dim i As Long, j As Long, dict As New Scripting.Dictionary
   Dim listB As msforms.listbox
   
   '在此处使用两个涉及的表格真正存在的工作表:
   Set tbl1 = ActiveSheet.ListObjects("T1.") '第一个表格对象
   Set tbl2 = ActiveSheet.ListObjects("T2.") '第二个表格对象
   
   arrT1 = tbl1.DataBodyRange.Value2 '将它们的内容放入数组以加快处理速度
   arrT2 = tbl2.DataBodyRange.Value2
   
   For i = 1 To UBound(arrT1)
        dict(arrT1(i, 1)) = vbNullString '提取唯一的客户号码
   Next i
   arrUnique = dict.keys '将字典键放入数组中
   dict.RemoveAll '清空字典以重新使用它...
   
   '在字典中加载必要的数据:
   For i = 1 To UBound(arrT2)
        mtch = Application.Match(arrT2(i, 1), arrUnique, True)
        If Not IsNumeric(mtch) Then
            If Not dict.Exists(arrT2(i, 1) & "|" & arrT2(i, 6)) Then
                dict.Add arrT2(i, 1) & "|" & arrT2(i, 6), Array(1, arrT2(i, 2), arrT2(i, 7))
            Else
                arrIt = dict(arrT2(i, 1) & "|" & arrT2(i, 6))   '将项目放入数组中
                arrIt(0) = arrIt(0) + 1 '计算出现次数
                arrIt(2) = arrIt(2) + arrT2(i, 7) '添加值
                dict(arrT2(i, 1) & "|" & arrT2(i, 6)) = arrIt '将更新后的项目数组放回
            End If
        End If
   Next i
   
   '加载最终数组:
   ReDim arFin(1 To dict.count, 1 To 5)
   For i = 1 To dict.count
        arFin(i, 1) = Split(dict.keys()(i - 1), "|")(0) '客户编号
        arFin(i, 3) = Split(dict.keys()(i - 1), "|")(1)  '拖欠的延迟
        arFin(i, 2) = dict.Items(i - 1)(1) '客户名
        arFin(i, 4) = dict.Items(i - 1)(0)  '发票数
        arFin(i, 5) = dict.Items(i - 1)(2)  '发票数
   Next i
   
   Set listB = ActiveSheet.OLEObjects("ListBox1").Object: '设置ActiveX列表框
   With listB
        .ColumnCount = UBound(arFin, 2) '设置列表框的列数
        .List = arFin '将数组内容放入列表框
   End With

End Sub

已编辑 以使用 Worksheets 而不是表格:

Sub LoadListBoxWithNotExistingCustomNoInSheets()
   Dim ws1 As Worksheet, ws2 As Worksheet, arrT1, arrT2, arrUnique, mtch, arrIt, arFin
   Dim i As Long, j As Long, dict As Object
   Dim listB As msforms.listbox
   
   Set ws1 = ActiveSheet '在此处使用您需要的工作表("My Summary Table")
   Set ws2 = ActiveSheet '一样的。我使用相同的工作表,因为我有两个表格,现在转化为范围("My Data source")...
   
   Dim lastR As Long
   lastR = ws1.Range("A" & ws1.Rows.Count).End(xlUp).Row '第一个表格的最后一行
   arrT1 = ws1.Range("A2:E" & lastR).Value2 '将其内容放入数组以加快处理速度
   
   lastR = ws2.Range("H" & ws2.Rows.Count).End(xlUp).Row '第二个表格的最后一行(注意要使用第一个范围列)
   arrT2 = ws1.Range("H2:N" & lastR).Value2 '您应该根据第二个工作表("My Data source")中需要的列来使用范围...

   Set dict = CreateObject("Scripting.Dictionary")

  '................
  '现有代码保持不变...
End Sub

如果与代码注释相关的某些内容不够清楚,请不要犹豫,要求澄清。

英文:

Please, use the next standard way. You must set your lisObjects (tables) from the place (worksheets) where they really exist. The active sheet must contain an ActiveX listbox, named "ListBox1":


Sub LoadListBoxWithNotExistingCustomNo()
   Dim tbl1 As ListObject, tbl2 As ListObject, arrT1, arrT2, arrUnique, mtch, arrIt, arFin
   Dim i As Long, j As Long, dict As New Scripting.Dictionary
   Dim listB As msforms.listbox
   
   'use here the real sheets where the two involved tables exist:
   Set tbl1 = ActiveSheet.ListObjects("T1.") 'the first table Object
   Set tbl2 = ActiveSheet.ListObjects("T2.") 'the second table Object
   
   arrT1 = tbl1.DataBodyRange.Value2 'place their contents in an array for faster processing
   arrT2 = tbl2.DataBodyRange.Value2
   
   For i = 1 To UBound(arrT1)
        dict(arrT1(i, 1)) = vbNullString 'extract the unique Customers numbers
   Next i
   arrUnique = dict.keys 'place the dictionary keys in an array
   dict.RemoveAll 'empty the dictionary to reuse it...
   
   'load in the dictionary the necessary data:
   For i = 1 To UBound(arrT2)
        mtch = Application.match(arrT2(i, 1), arrUnique, True)
        If Not IsNumeric(mtch) Then
            If Not dict.Exists(arrT2(i, 1) & "|" & arrT2(i, 6)) Then
                dict.Add arrT2(i, 1) & "|" & arrT2(i, 6), Array(1, arrT2(i, 2), arrT2(i, 7))
            Else
                arrIt = dict(arrT2(i, 1) & "|" & arrT2(i, 6))   'place the item in an array
                arrIt(0) = arrIt(0) + 1 'count the number of occurrences
                arrIt(2) = arrIt(2) + arrT2(i, 7) 'add the values
                dict(arrT2(i, 1) & "|" & arrT2(i, 6)) = arrIt 'drop back the updatred ltem array
            End If
        End If
   Next i
   
   'load the final array:
   ReDim arFin(1 To dict.count, 1 To 5)
   For i = 1 To dict.count
        arFin(i, 1) = Split(dict.keys()(i - 1), "|")(0) 'the customer Number
        arFin(i, 3) = Split(dict.keys()(i - 1), "|")(1)  'the aged delay
        arFin(i, 2) = dict.Items(i - 1)(1) 'Customer name
        arFin(i, 4) = dict.Items(i - 1)(0)  'Count of Invoices
        arFin(i, 5) = dict.Items(i - 1)(2)  'Count of Invoices
   Next i
   
   Set listB = ActiveSheet.OLEObjects("ListBox1").Object: 'set the ActiveX list box
   With listB
        .ColumnCount = UBound(arFin, 2) 'set the list box number of columns
        .List = arFin 'drop the array content in the list box
   End With

End Sub

Edited for using Worksheets instead of Tables:

Sub LoadListBoxWithNotExistingCustomNoInSheets()
   Dim ws1 As Worksheet, ws2 As Worksheet, arrT1, arrT2, arrUnique, mtch, arrIt, arFin
   Dim i As Long, j As Long, dict As Object
   Dim listB As msforms.listbox
   
   Set ws1 = ActiveSheet 'use here the sheet you need ("My Summary Table")
   Set ws2 = ActiveSheet 'the same. I am using the same sheet because I had two tables, now transformed in ranges ("My Data source")...
   
   Dim lastR As Long
   lastR = ws1.Range("A" & ws1.rows.count).End(xlUp).row 'last row for the former first table
   arrT1 = ws1.Range("A2:E" & lastR).Value2  'place their contents in an array for faster processing
   
   lastR = ws2.Range("H" & ws2.rows.count).End(xlUp).row 'last row for the former second table (take care of the first range column TO BE USED)
   arrT2 = ws1.Range("H2:N" & lastR).Value2 'you should use your range in terms of necessary columns from second sheet ("My Data source")...

   Set dict = CreateObject("Scripting.Dictionary")

  '................
  'the existing code remains unchanged...
End Sub

If something not clear enough related to the code comments, do not hesitate to ask for clarifications.

Edit 2

Microsoft Scripting Runtime reference can be added running the next piece of code:

Sub addScrRunTimeRef()
  'Add a reference to 'Microsoft Scripting Runtime':
  'In case of error ('Programmatic access to Visual Basic Project not trusted'):
  'Options->Trust Center->Trust Center Settings->Macro Settings->Developer Macro Settings->
  '         check "Trust access to the VBA project object model"
  Application.vbE.ActiveVBProject.References.AddFromFile "C:\Windows\SysWOW64\scrrun.dll"
End Sub

huangapple
  • 本文由 发表于 2023年6月29日 16:49:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76579491.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定