Cộng tổng trong Treeview (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

ctinvoipex

Thành viên mới
Tham gia
9/12/08
Bài viết
7
Được thích
0
Em có bài này đã tìm hiểu lâu rồi mà chưa có thuật toán nào gỡ rối được mong các thầy gỡ rối giùm
Chủ đê cộng tổng các giá trị Child trong cấp Parent, thực hiện hiển thị ra trên Treeview.
em biết treeview là rất khó nên nhờ các thầy giúp em với. Thankssssss

file mẫu
 

File đính kèm

Lần chỉnh sửa cuối:
Em có bài này đã tìm hiểu lâu rồi mà chưa có thuật toán nào gỡ rối được mong các thầy gỡ rối giùm
Chủ đê cộng tổng các giá trị Child trong cấp Parent, thực hiện hiển thị ra trên Treeview.
em biết treeview là rất khó nên nhờ các thầy giúp em với. Thankssssss

file mẫu

Chỉ "con" thôi hay cả "cháu, chắt, chít ..."? Trong tổng này có tính cả giá trị "cha" không?

Mà nếu bạn muốn cám ơn thì nói tiếng Việt nhé. Người Việt cám ơn nhau mà phải dùng tiếng Anh mới đủ diễn đạt được lòng biết ơn của mình?. Đá tiếng Anh tùy lúc thôi. Xin lỗi, cám ơn nên nói bằng tiếng Việt.
 
Lần chỉnh sửa cuối:
Upvote 0
Em có bài này đã tìm hiểu lâu rồi mà chưa có thuật toán nào gỡ rối được mong các thầy gỡ rối giùm
Chủ đê cộng tổng các giá trị Child trong cấp Parent, thực hiện hiển thị ra trên Treeview.
em biết treeview là rất khó nên nhờ các thầy giúp em với. Thankssssss

file mẫu
Bạn xem thử file này nhé.
 

File đính kèm

Upvote 0
Cảm ơn bác siwtom đã góp ý. Tất nhiên là cộng tổng cả các cấp con vô cùng (chút chít .....).

Bác huuthang_bd , đây là thuật toán treeview, và dữ liệu phân xưởng, tổ 1 tổ 2 chỉ là mẫu thôi, nếu trong trường hợp khác ta thêm nhiều cấp con, cháu chút chít,.... thì có cộng tổng được ở tất cả các cấp con bên trong đó không?
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn bác siwtom đã góp ý. Tất nhiên là cộng tổng cả các cấp con vô cùng (chút chít .....).

Bác huuthang_bd , đây là thuật toán treeview, và dữ liệu phân xưởng, tổ 1 tổ 2 chỉ là mẫu thôi, nếu trong trường hợp khác ta thêm nhiều cấp con, cháu chút chít,.... thì có cộng tổng được ở tất cả các cấp con bên trong đó không?
Như bạn siwtom đã hỏi. Do bạn hỏi không rõ ràng nên lại mất công. Bạn đưa dữ liệu tổng quát lên mọi người sẽ làm tiếp.
 
Upvote 0
Cảm ơn bác siwtom đã góp ý. Tất nhiên là cộng tổng cả các cấp con vô cùng (chút chít .....).

Bác huuthang_bd , đây là thuật toán treeview, và dữ liệu phân xưởng, tổ 1 tổ 2 chỉ là mẫu thôi, nếu trong trường hợp khác ta thêm nhiều cấp con, cháu chút chít,.... thì có cộng tổng được ở tất cả các cấp con bên trong đó không?

Tôi lường được trường hợp này nên hỏi cho khỏi mất công.
Thuật toán không có gì khó. Bạn có "ông bố" nào đấy, ông bố đầu chắc lấy trong NodeClick. Có thì đọc được giá trị của ông bố. Sau đó tìm con đầu lòng của ông bố - node.child. Sau đó tìm con tiếp theo, tức em của child kia - node.Next (node là nói về Object node của TreeView - ở đây là tìm child.Next). Tìm tới khi hết con thì thôi (Nothing). Muốn tìm cháu, chắt chít thì khi tìm được "vị" nào thì coi vị đó là "ông bố" mới và lặp lại thuật toán. Để đơn giản thì dùng đệ quy.
Về giá trị gán cho node: node có một thuộc tính để người dùng sử dụng tùy theo nhu cầu của mình - đó là Tag. Vậy:
1. Khi bạn thêm node thì gán luôn giá trị cho nó vào Tag, tức
Mã:
Set node = ...
[COLOR=#ff0000]node.Tag = ...[/COLOR]
2.
Mã:
Sub SumAll(node As MSComctlLib.node, tong As Long)
Dim child As MSComctlLib.node
    ' cộng giá trị của "bố"
    tong = tong + node.Tag
    ' tìm con đầu lòng
    Set child = node.child
    Do While Not child Is Nothing
        ' coi con là "bố" khác và lặp lại thuật toán cho ổng 
        SumAll child, tong
        ' tìm con tiếp theo, tức em của con trước
        Set child = child.Next
    Loop
End Sub

Private Sub TreeView1_NodeClick(ByVal node As MSComctlLib.node)
Dim tong As Long
    TextBox1.Text = node.Text
    TextBox2.Text = node.Tag
    tong = 0
    SumAll node, tong
    TextBox3.Text = tong
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Code của bác siwtom lỗi ko chạy được ở đoạn :

' cộng giá trị của "bố" tong = tong + node.Tag
vì kiểu của tong là Long, mà Node.tag nó trả về kiểu String hay arr gì đó.
Em thử dùng Val(node.tag) thì ko thấy nó báo lỗi nhưng không nhân được kết quả.

Nhưng rất tuyệt vời là Code củaBác huuthang_bd em thêm các cấp Child thì thấy OK , mà đúng ý em đang muốn hỏi, tuyệt quá.
Cảm ơn bác huuthang_bd , vô cùng tận.

À em đã Kiểm tra lại thì có 1 vấn đề : Nó chỉ cộng được tổng cấp Parent trong cùng thoi, cấp ngoài thì nó không cộng được tức là chỉ cộng được 1 cấp thôi. Có cách nào cộng được tất cả các cấp Child không nhỉ? kể cả cộng tổng của cả phân xưởng luôn ấy.
Nhờ các Bác tham mưu giúm nhé!
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Code của bác siwtom lỗi ko chạy được ở đoạn :

' cộng giá trị của "bố" tong = tong + node.Tag
vì kiểu của tong là Long, mà Node.tag nó trả về kiểu String hay arr gì đó.
Em thử dùng Val(node.tag) thì ko thấy nó báo lỗi nhưng không nhân được kết quả.

Bạn ạ, tôi đâu phải người không test mà cứ nói bừa. Nếu tôi đã bỏ công ra viết code cụ thể thì bao giờ tôi cũng kiểm tra. Tôi không giúp thì thôi chứ đã giúp thì làm rất có trách nhiệm.
Tôi nói là khi tạo mỗi node thì thêm giá trị của nó vào Tag, bạn có làm không?
Tag là Variant thì chả lý gì Tong = Tong + node.Tag lại "không chạy"
Nếu bạn nói: "không biết em làm sai ở đâu mà có lỗi", và bạn đính kèm code của tôi thì tôi sẽ giúp bạn tìm chỗ sai. Nhưng bạn nói:
Code của bác siwtom lỗi ko chạy được ở đoạn :
' cộng giá trị của "bố" tong = tong + node.Tag
và bạn không đính kèm code của tôi, vì code
Mã:
Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
Dim Tong As Long, i As Long
Me.TextBox1.Text = Node.Text
Me.TextBox2.Text = ArrTemp(Dic.Item(Node.Key), 5)
Tong = ArrTemp(Dic.Item(Node.Key), 5)
On Error GoTo Show
Set Node = Node.Child
Tong = Tong + ArrTemp(Dic.Item(Node.Key), 5)
For i = 2 To Node.Parent.Children
    Set Node = Node.Next
    Tong = Tong + ArrTemp(Dic.Item(Node.Key), 5)
Next
Show:
Me.TextBox3.Text = Tong
End Sub
chắc chắn không phải của tôi.

Vậy thì tôi chỉ cm rằng code của tôi chạy đúng mà thôi.

View attachment 88291
Tất nhiên tôi không bỏ công để tìm giá trị của mỗi node vì chúng cũng chỉ là ví dụ. Vậy khi tạo node thì tôi gán vào Tag các số thứ tự (tính từ 0) tăng dần
Thế thôi nhé, tôi chỉ cm rằng code chạy đúng. Tôi không tham gia nữa, bạn tự tìm nhé.
Mà nếu đã định nhờ tiếp để sửa thì cũng nên nói lời cám ơn người đã bỏ công ra giúp mình.
 
Upvote 0
Trước tiên rất xin lỗi vì đã nói rằng Code của bác bị lỗi. Em đã nghiên cứu về mặt thuật toán thấy vòng lặp đã duyệt được hết các giá trị Node nhưng quả thực trên máy của em nó vẫn chư chạy được, em gửi file đã ghép Code của bác với dữ liệu bác test dùm em với nhé.
và trên thực tế thông báo lỗi và file em nhờ bác siwtom xem giùm
 

File đính kèm

  • type mismatch1.JPG
    type mismatch1.JPG
    153.4 KB · Đọc: 7
  • type mismatch2.JPG
    type mismatch2.JPG
    166.3 KB · Đọc: 8
  • TreeViewControl siwtom.rar
    TreeViewControl siwtom.rar
    57.8 KB · Đọc: 27
Upvote 0
Trước tiên rất xin lỗi vì đã nói rằng Code của bác bị lỗi. Em đã nghiên cứu về mặt thuật toán thấy vòng lặp đã duyệt được hết các giá trị Node nhưng quả thực trên máy của em nó vẫn chư chạy được, em gửi file đã ghép Code của bác với dữ liệu bác test dùm em với nhé.
và trên thực tế thông báo lỗi và file em nhờ bác siwtom xem giùm

Tôi đã nói không tham gia rồi, nhưng thôi tôi viết ngắn gọn thôi. Vì:

1. Muốn đọc node.Tag thì trước hết phải nhập giá trị vào Tag, lôgíc quá đúng không?
Và nữa: Tôi đã viết rất rõ ràng trong bài đầu:

Về giá trị gán cho node: node có một thuộc tính để người dùng sử dụng tùy theo nhu cầu của mình - đó là Tag. Vậy:
1. Khi bạn thêm node thì gán luôn giá trị cho nó vào Tag, tức
Mã:
Set node = ...
node.Tag = ...

Tại sao bạn không làm??????????????????????????????? Bạn trả lời câu hỏi này cho tôi!

Đã bảo làm mà không làm.

Nhập vào Tag, nếu cái nào không có giá trị thì nhập 0

2. Bạn chỉ biết nhặt rồi đi.

Tôi không muốn kéo dài nữa. Tôi viết rất rõ ràng nhưng bạn có làm theo đâu. Không làm theo rồi kêu code sai. Bótay.toàntập.com
 
Lần chỉnh sửa cuối:
Upvote 0
Bàn thêm!

Xin bổ sung thêm một số chia sẻ cho vấn đề đã trình bày trong bài viết. Tôi xin phép bác huuthang sửa đoạn code của bác. Trên thực tế ta không cần phải dùng đến đối tượng Dictionary trong bài toán này. Khi nghiên cứu kỹ lý do phải dùng Dic của bác, tôi thấy có lẽ không nhất thiết phải phức tạp hóa như vậy.
Lý thuyết cơ bản của yêu cầu chỉ là:
1. Dựa vào cấu trúc dữ liệu của tác giả, xây dựng thuật toán đưa chúng vào cấu trúc TreeView;
2. Căn cứ vào việc lựa chọn đối tượng, tính toán tổng sản lượng tạo ra bởi các đối tượng con của đối tượng hiện tại đang lựa chọn.

Tuy nhiên, khi xem xét vào cấu trúc dữ liệu và cách đặt vấn đề, tôi thấy có một vài điểm yếu

1. Liên quan đến xây dựng cấu trúc cây dữ liệu
Thông thường để lưu quản lý dữ liệu dạng cây, người ta cần có cách nào đó để tránh phải xác định thứ tự các nhánh cha/con một cách thủ công.
Với trường hợp hiện tại, bạn đang phải sắp xếp một cách thủ công và rất dễ xảy ra lỗi cấu trúc.
Thuật toán dựng cây của bác Huuthang là xét tuần tự dựa vào thiết lập dữ liệu đã có sẵn. Nếu có lỗi về sắp xếp: ví dụ, một đối tượng con tham chiếu đến đối tượng cha lại chưa được thêm vào cây (nằm ở các dòng sau) thì sẽ phát sinh lỗi.
Chính vì thế, trong thực tế, người ta có 2 cách tiếp cận xây dựng CSDL cho cây
1. Xác lập mối liên quan cha con theo dạng dữ liệu có thể sắp xếp được ví dụ 01 và 01.01 ...vv (giống cách của bạn nhưng theo một quy tắc định trước trong đó nếu sắp xếp theo trường Key thì sẽ luôn luôn có các Node ở cấp gốc đứng đầu).
2. Dùng biện pháp quét ngang qua toàn cây với 2 trường thuộc tính trái/phải của một node trong đó node gốc sẽ có trường trái bắt đầu từ 1 và phải kết thúc bằng tổng sô nodex2.
Cách này hiện nay được dùng khá nhiều do không phải sử dụng thuật toán đệ quy khi tải dữ liệu. Tuy nhiên, mỗi khi có sự thêm/bớt node thì người ta phải xây dựng lại thuộc tính trái/phải của cấu trúc cây (Link tham khảo này khá thú vị http://www.sitepoint.com/hierarchical-data-database-2/). Về chủ đề này, nếu các bạn quan tâm, tôi có thể viết hoặc lược dịch một số bài viết hay để tham khảo.

2. Liên quan đến tính toán số liệu
Căn cứ vào bài viết, có thể thấy rõ, số liệu chỉ nằm ở các phần tử cấp thấp nhất (nói khác hơn, chỉ các công nhân mới tạo ra sản lượng). Vì thế, trong bài viết của bạn, mặc dù tôi đã viết lại thuật toán tính tổng nhưng với các đối tượng cha, do chúng có thuộc tính QTY là rỗng vì thế bất kể ở cấp Cha nào, thuật toán sẽ tự tìm kiếm các đối tượng có số liệu ở cấp thấp nhấp để tính.


PHP:
Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
    ' Tôi sửa lại một chút code của bác Huuthang để cho đơn giản
    Dim Tong As Long, i As Long
    TextBox1.Text = Node.Text
    TextBox2.Text = Node.Tag
    TextBox3.Text = GetTotal(Node)
End Sub


Private Function GetTotal(ByVal Node As Node) As Single
    ' Hàm này để tính tổng tất cả các node con
    Dim i As Integer, nodX As Node
    If Node.Children <> 0 Then 'Nếu Node này có node con
        Set nodX = Node.Child 'Lấy Node con đầu tiên
        For i = 1 To Node.Children 'Duyệt qua từng node
            GetTotal = GetTotal + GetTotal(nodX)
            Set nodX = nodX.Next 'Gán cho Node con tiếp theo
        Next
    Else
        GetTotal = Val(Node.Tag)
    End If
End Function


Private Sub CreateTreeView()
    'Nhập vào Treeview
    Dim ArrTemp As Variant, i As Long, Node As Node
    UserForm1.TreeView1.Nodes.Clear


    ' Tạo ra một mảng từ vùng dữ liệu
    ArrTemp = Range([A65536].End(xlUp), [A2]).Resize(, 6).Value    
    
    For i = 1 To UBound(ArrTemp, 1)
        With TreeView1
            If ArrTemp(i, 3) = "" Then
                Set Node = .Nodes.Add(, , ArrTemp(i, 2), ArrTemp(i, 1), ArrTemp(i, 4))
            Else
                Set Node = .Nodes.Add(ArrTemp(i, 3), tvwChild, ArrTemp(i, 2), ArrTemp(i, 1), ArrTemp(i, 4))
            End If
            ' Gán giá trị của Node vào thuộc tính Tag để tính toán cho dễ
            Node.Tag = ArrTemp(i, 5)
            Node.Expanded = True
        End With
    Next
End Sub
 

File đính kèm

Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Quên mất, tôi có sửa tên thủ tục Familytree.... thành CreateTree vì thế bạn copy code trên vào chắc sẽ không chạy được. Bạn xem lại file đính kèm trong bài viết trước sẽ thấy nhé.
 
Upvote 0
Thank bác paulsteigel. Em test OK rồi. chạy ổn. File bác đính kèm thì ko chạy vì trong Form bị xóa mất cái Treeview nhưng thêm cái treeview vào chạy Tít. Cảm ơn các bác rất rất nhiều.
Em cũng cảm ơn bác siwtom, bác huuthang đã tham gia góp ý xây dựng cho bài tập này của em.
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Chào bạn! .Mình cũng mới học VBA. Mình cũng đang thắc mắc một số vấn đề về treeview:
bạn có thể chỉ giúp mình làm nút Showtreeview được không, thankssssssssssssss
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom