Tach các cột tạo thành một mảng mới (1 người xem)

Liên hệ QC

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

Yeuvoyeucon

Thành viên hoạt động
Tham gia
30/10/09
Bài viết
143
Được thích
23
Kính gửi anh chị và các bạn,

Giả sử em có bảng số liệu từ A đến cột G. Bình thường để add bảng dữ liệu này vào mảng thì ta dung lệnh sau

lr = .Range("A" & Rows.Count).End(xlUp).Row

arr = .Range("A2:G" & lr).Value

Bây giờ, em muốn tạo một mảng cũng trích từ bảng này nhưng chỉ lấy thứ tự theo các cột sau: Lấy cột A, Cột C, Cột G. Có cách viết như thế nào để viết chỗ này hay bắt buộc phải Redim từ mảng arr thành một mảng 3 chiều như ta vẫn thường làm ạ.
 

File đính kèm

Quan trọng là mục đích CUỐI CÙNG là gì ấy. Chứ nêu tạo mảng chứa 3 cột đó không có ý nghĩa gì cả.
 
Upvote 0
Quan trọng là mục đích CUỐI CÙNG là gì ấy. Chứ nêu tạo mảng chứa 3 cột đó không có ý nghĩa gì cả.
Em đang cần làm một số bước mà cần 3 cột đó liền nhau ạ. Bình thường thì redim rồi em dán lại mảng 3 cột cần lấy này ra sheet. Rồi lại tính toán trên bảng này, như thế nó hơi dài dòng ạ.
 
Upvote 0
Em đang cần làm một số bước mà cần 3 cột đó liền nhau
Tôi biết bạn đang cần làm gì đó nên mới đăng bài hỏi.

Và cũng vì thế nên mới hỏi mục đích CUỐI CÙNG là gì để giải quyết '1 đập ăn quan'.
Bởi phương án kia mới là ý tưởng của bạn mà thôi, biết đâu đấy còn cách khác có khi không liên quan gì mảng này cả.
 
Upvote 0
Tôi biết bạn đang cần làm gì đó nên mới đăng bài hỏi.

Và cũng vì thế nên mới hỏi mục đích CUỐI CÙNG là gì để giải quyết '1 đập ăn quan'.
Bởi phương án kia mới là ý tưởng của bạn mà thôi, biết đâu đấy còn cách khác có khi không liên quan gì mảng này cả.
Ý của em là cần một mảng mới mà 3 cột đó liền nhau ạ. Làm theo bình thường redim, rồi lọc 3 cột đó ra từ mảng arr đầu thì đơn giản. Nhưng em muốn hỏi có cách nào viết cái chỗ này mà mảng nó vẫn hiểu là 3 cột đó không ạ
arr = .Range("Cột A, C, G" & lr).Value
 
Upvote 0
Bây giờ, em muốn tạo một mảng cũng trích từ bảng này nhưng chỉ lấy thứ tự theo các cột sau: Lấy cột A, Cột C, Cột G. Có cách viết như thế nào để viết chỗ này hay bắt buộc phải Redim từ mảng arr thành một mảng 3 chiều như ta vẫn thường làm ạ.
mảng 3 chiều tức là Redim b(1 To n1, 1 To n2, 1 To n3)
Tôi chưa thấy kiểu nào trong GPE bắt buộc phải pàm vậy cả.

Chép lại mảng cách cột là công việc khá vô duyên.
Người ta chép lại cả mảng rồi delete những cột không cần thiết.
 
Upvote 0
mảng 3 chiều tức là Redim b(1 To n1, 1 To n2, 1 To n3)
Tôi chưa thấy kiểu nào trong GPE bắt buộc phải pàm vậy cả.
Thớt 'lỡ tay' gõ vậy thôi anh. :)

Chép lại mảng cách cột là công việc khá vô duyên.
Người ta chép lại cả mảng rồi delete những cột không cần thiết.

Em đoán thớt cần lấy 3 cột ở xa nhau kia sang một sheet/range khác (và không muốn dùng vòng lặp xét từng dòng). Mà hỏi mãi không chịu hé răng ra.
Thớt mà nói ra thì 2 giây là xong lâu rồi.
 
Upvote 0
Thớt 'lỡ tay' gõ vậy thôi anh. :)



Em đoán thớt cần lấy 3 cột ở xa nhau kia sang một sheet/range khác (và không muốn dùng vòng lặp xét từng dòng). Mà hỏi mãi không chịu hé răng ra.
Thớt mà nói ra thì 2 giây là xong lâu rồi.
Em không hiểu ý của anh hỏi, chứ mong muốn của em chỉ là: Có cách nào biểu diễn arr = .Range("Cột A, C, G" & lr).Value hay phải làm Redim một mảng mới và dán nó ra sheet và làm tiếp tục trên nó.
Cái này em hỏi nó giống như ở SQL mình dùng cấu trúc để tạo ra một bảng và lại xử lý tiếp trên nó.
WITH expression_name[(column_name [,...])]
AS
(CTE_definition)
SQL_statement;
 
Upvote 0
Upvote 0
Trong VBA dùng Index() là lấy được cột.
...
Không dễ như vậy.
Có hai cách để làm:
1. Union các cột lại thành một range chính.
Kế đó đọc range này vào một array.
Bởi vì Union là một mảng 3 chiều, mỗi vùng range trong union là một area. Cách đọc trực tiếp chỉ lấy được area 1. Phải dùng vòng lặp để lấy từng area vào từng mảng con của array (array kết quả là một array răng cưa - jagged array)
Ghi ngược lại cũng là qua vòng lặp, từng mảng con.
Cáchn này đòi hỏi trình đô hiểu biết về mảng khá cao.
2. Dùng hàm Evaluate để tính một biểu thức công thức trên bảng tính. Công thức này có thể dùng Index hay dễ hơn là dùng hàm choose để ghép nhiều cột lại thành 1 mảng 2 chiều.
Cột này đòi hỏi trình độ về mảng tuonwg đói những trình độ hiểu Evaluate khá sâu.
(lưu ý là tôi dùng từ ngữ rất chính xác. Khi tôi nói trình độ hiểu biết cao là tôi muốn nói cao - tức biết sử dụng rất thuần thục, khi nói sâu là tôi muốn nói sâu, tức căn bản rất chắc)

Chú thích: cái chủ trương "càng nhiều bài càng tốt, càng nhiều người mới càng quý" của chủ diễn đàn đi theo cái phản ứng phụ là làm giảm chất lượng.
Một trong những phản ứng phụ là người trả lời chịu khó phân tích, giải thích câu trả lời của mình. Trong khi người hỏi không buồn cải tiến cách đặt câu cú, cách trình bày vấn đề của mình.
Thế giới GPE có ngược ngạo thế đấy. Người không có nhiều nhu cầu cải tiến thì luôn cố gắn. Ngwoif đáng lẽ phải luon cải tiến kỹ năng giao tiếp thì hời hợt, coi diễn đàn như cái chợ, cần món gì thì tạt vào mua. Lắm lúc thiếu suyn nghĩ đến mức cần cá mà vào chợ hỏi mua thịt.
 
Upvote 0
Dùng Index() lấy được cột mà anh.

PHP:
Option Explicit

Sub vidu()
    Const sRngData = "A2:E10"
    Const sCellTarget = "H2"
    Dim data As Variant, listIndex As Variant, numRows As Long, item As Variant, iCol As Long
    data = Sheet1.Range(sRngData).Value
    listIndex = VBA.Array(1, 3, 5)  'Lay cot A, C, E '
    numRows = UBound(data, 1)
    For Each item In listIndex
        Sheet1.Range(sCellTarget).Offset(0, iCol).Resize(numRows, 1).Value = Application.index(data, , VBA.CLng(item))
        iCol = iCol + 1
    Next item
End Sub
 
Upvote 0
Dùng Index() lấy được cột mà anh.

PHP:
Option Explicit

Sub vidu()
    Const sRngData = "A2:E10"
    Const sCellTarget = "H2"
    Dim data As Variant, listIndex As Variant, numRows As Long, item As Variant, iCol As Long
    data = Sheet1.Range(sRngData).Value
    listIndex = VBA.Array(1, 3, 5)  'Lay cot A, C, E '
    numRows = UBound(data, 1)
    For Each item In listIndex
        Sheet1.Range(sCellTarget).Offset(0, iCol).Resize(numRows, 1).Value = Application.index(data, , VBA.CLng(item))
        iCol = iCol + 1
    Next item
End Sub
Nó cũng là chép lại từng cột như mảng răng cưa như tôi nói ở bài trên. Thà dùng thẳng mảng răng cưa ít nhầm lẫn hơn.
 
Upvote 0
Kính gửi anh chị và các bạn,

Giả sử em có bảng số liệu từ A đến cột G. Bình thường để add bảng dữ liệu này vào mảng thì ta dung lệnh sau

lr = .Range("A" & Rows.Count).End(xlUp).Row

arr = .Range("A2:G" & lr).Value

Bây giờ, em muốn tạo một mảng cũng trích từ bảng này nhưng chỉ lấy thứ tự theo các cột sau: Lấy cột A, Cột C, Cột G. Có cách viết như thế nào để viết chỗ này hay bắt buộc phải Redim từ mảng arr thành một mảng 3 chiều như ta vẫn thường làm ạ.
Cái này dùng mảng trong mảng là được, có cái là khi tra cứu phần tử, các chỉ số có hơi khác so với mảng 2 chiều bình thường
 
Upvote 0
Minh hoạ cách 2 như tôi nói ở bài #11

1634621944296.png
 

File đính kèm

  • 1634621198752.png
    1634621198752.png
    34.6 KB · Đọc: 3
Upvote 0
Minh hoạ cách 2 như tôi nói ở bài #11

View attachment 267963
Em đã thử với dữ liệu và code chạy đúng ý em ạ. NHưng có một vấn đề là dòng cuối lastrow thì mình có thể viết thế nào anh !. Em đã thử như dưới mà không được ạ.

Sub tt()
With Sheet1
Dim arr(), lr&
lr = .Range("A" & Rows.Count).End(xlUp).Row
arr = Evaluate("Choose({1,2,3},"A1:A"&lr,"C1:C"&lr,"G1:G"&lr)")
.Range("K2").Resize(lr, 3).Value = arr 'Thử in ra sheet
End With


End Sub
 
Upvote 0
Hàm Evaluate chỉ nhận một biểu thức có giá trị là string:

a = Evaluate(Replace("Choose({1,2,3}, A1:A<sd>,C1:C<sd>,G1:G<sd>)", "<sd>", CStr(lr)))

Nếu không muón dùng Evaluate thì cũng có thể dùng hàm Application.Choose. Nhưng cách gọi hơi rắc rối hơn một chút:

a = Application.Choose([ { 1, 2, 3 } ], Range("A1:A" & lr), Range("C1:C" & lr), Range("G1:G" & lr))
Lưu ý là VBA không chấp nhận dấu { }, muốn gọi biểu thức có dấu này thì phải gói qua Evaluate. Trong biểu thức trên, hàm Evaluate được viết tắt bằng [ ].

Lưu ý quan trọng: như tôi đã nhắc ở bài #11. Lấy giá trị kiểu này hơi nguy hiểm, người dùng nên check trước là hàm choose ở trên trả về giá trị Value hay Value2.
 
Lần chỉnh sửa cuối:
Upvote 0
Hàm Evaluate chỉ nhận một biểu thức có giá trị là string:

a = Evaluate(Replace("Choose({1,2,3}, A1:A<sd>,C1:C<sd>,G1:G<sd>)", "<sd>", CStr(lr)))

Nếu không muón dùng Evaluate thì cũng có thể dùng hàm Applicasiton.Choose. Nhưng cách gọi hơi rắc rối hơn một chút:

a = Application.Choose([ { 1, 2, 3 } ], Range("A1:A" & lr), Range("C1:C" & lr), Range("G1:G" & lr))
Lưu ý là VBA không chấp nhận dấu { }, muốn gọi biểu thức có dấu này thì phải gói qua Evaluate. Trong biểu thức trên, hàm Evaluate được viết tắt bằng [ ].

Lưu ý quan trọng: như tôi đã nhắc ở bài #11. Lấy giá trị kiểu này hơi nguy hiểm, người dùng nên check trước là hàm choose ở trên trả về giá trị Value hay Value2.
Code chạy đúng rồi ạ. Em cảm ơn anh nhiều ạ .
 
Upvote 0
Nó cũng là chép lại từng cột như mảng răng cưa như tôi nói ở bài trên.
Theo em gọi là mảng răng cưa có thể tạo cảm giác phức tạp và bị giới hạn (tương tự gọi là 'mảng trong mảng').
Nếu nắm chắc định nghĩa về mảng sẽ linh hoạt hơn.
Đơn giản phần tử của mảng có thể là 1 giá trị, object, array hay bất kể loại dữ liệu nào đó, rồi trong mỗi phần tử đó lại chứa những kiểu dữ liệu khác đan xen trong nó. Điển hình như kiểu dữ liệu json.
Có vẻ những thành viên đi trước tạo ra những ảnh hưởng nhất định tới những thành viên sau về cách tiếp cận lý thuyết, hoặc ít có cơ hội/ bài toán cần xây dựng mô hình phức tạp kia.


Thà dùng thẳng mảng răng cưa ít nhầm lẫn hơn.
Em thấy dùng Evaluate, Applicasiton.Choose phức tạp hơn dùng Index() rồi.
Chưa kể cách dùng Index() còn áp dụng trường hợp khi có mảng kết quả cần ghi xuống những cột không liên tiếp.
 
Upvote 0
...
Đơn giản phần tử của mảng có thể là 1 giá trị, object, array hay bất kể loại dữ liệu nào đó, rồi trong mỗi phần tử đó lại chứa những kiểu dữ liệu khác đan xen trong nó. Điển hình như kiểu dữ liệu json.
Có vẻ những thành viên đi trước tạo ra những ảnh hưởng nhất định tới những thành viên sau về cách tiếp cận lý thuyết, hoặc ít có cơ hội/ bài toán cần xây dựng mô hình phức tạp kia.
...
Kiểu dữ liệu JSON là kiểu dữ liệu của JavaScript. Nó là Object chứ phông phải mảng.

Mảng là lối cấu trúc cổ điển nhất trong lập trình. Vì cổ điển cho nên nó bắt buộc phải rất hiệu quả (trong giới hạn của nó), đặc biệt là các phần tử bắt buộc phải liên tiếp nhau trong bộ nhớ.

Về sau này, các ngôn ngữ mới như JavaScript, Python ỷ trượng vào sức mạnh của máy đời sau (có nhớ ngày xưa khi Intel ra 80286 thay thế 8088/8086 đã là rầm rộ, Pentium thay 80486 lại càng dữ dội hơn - Pent là 5, chắc ý họ nói 80586) nên dùng cấu trúc dạng XML cho dễ parse. VBx, VBA bắt buộc phải thêm mấy cái COM để đối phó.
Riêng Python ỷ trượng vào đống thư viện khổng lồ mà các tay hảo tâm viết (thường thì bằng C nên rất hiệu quả). Đã qua sàng lọc ngon lành cho nên càng ngày càng mạnh. Và nhất là đống cấu trúc dữ liệu, các giao diện trong thư viện rất mạnh. Chính Python thì nó chỉ là một cái sàn viết script thôi.
Sức mạnh của Python chính thức là do nhóm cha đẻ ra nó đã có cái nhìn khách quan (tôi nghĩ qua kinh nghiệm GCC) cho nên họ đặt ngôn ngữ này có thể nhập (import) thư viện hết sức dễ dàng.
 
Upvote 0
Mảng răng cưa là tên gọi phổ biến, chả có gì là phức tạp vấn đề ở đây, mảng trong mảng cũng vậy.
Làm gì có "mảng object, array hay bất kể loại dữ liệu nào", đọc thế này làm như phần tử mảng là cái nhà kho chắc.
 
Upvote 0
Đọc phải chuẩn chỉ từng ký tự thì mới hiểu biết được. Thêm mắm muối vào là lệch lạc ngay.
 
Upvote 0
Mảng răng cưa là tên gọi phổ biến, chả có gì là phức tạp vấn đề ở đây, mảng trong mảng cũng vậy.
Làm gì có "mảng object, array hay bất kể loại dữ liệu nào", đọc thế này làm như phần tử mảng là cái nhà kho chắc.

Mặt ngoài: chính xác, mỗi phần tử của mảng Aray là cái nhà kho. Nhà kho thì chứa cài gì xũng được. Nói theo tiếng xưa là "từ cây kim đến chiếc phi thuyền"

Bên trong: hơi phức tạp chút. Mảng đã xác phần tử kiểu đơn giản thì mỗi phần tử chứa trực tiếp trị số. Mảng có phần tử phức tạp thì mỗi phần tử chứa địa chỉ của chỗ chứa dữ liệu thực sự.
Ta có thể coi như kiểu một là dãy nhà kho san sát nhau, và kiểu thứ hai là một danh sách địa chỉ nhà kho. Đến với mảng 1 ta có thể đi thẳng vào nhà kho số n. Đến với mảng 2 là ta lấy cái địa chỉ nhà kho n và tìm đến nhà kho ấy.

Mảng răng cưa là phản ứng tiếp theo khi về sau này, người ta nhận ra là cách xếp mảng đơn giản không đáp ứng được một số trường hợp. Với VBA, mảng răng cưa có thể coi như "mảng trong mảng". Nhưng với các ngôn ngữ thì chưa chắc.
 
Upvote 0
Mặt ngoài: chính xác, mỗi phần tử của mảng Aray là cái nhà kho. Nhà kho thì chứa cài gì xũng được. Nói theo tiếng xưa là "từ cây kim đến chiếc phi thuyền"

Bên trong: hơi phức tạp chút. Mảng đã xác phần tử kiểu đơn giản thì mỗi phần tử chứa trực tiếp trị số. Mảng có phần tử phức tạp thì mỗi phần tử chứa địa chỉ của chỗ chứa dữ liệu thực sự.
Ta có thể coi như kiểu một là dãy nhà kho san sát nhau, và kiểu thứ hai là một danh sách địa chỉ nhà kho. Đến với mảng 1 ta có thể đi thẳng vào nhà kho số n. Đến với mảng 2 là ta lấy cái địa chỉ nhà kho n và tìm đến nhà kho ấy.
Về cái "danh sách địa chỉ" như bác nói thì đồng ý. Đã nói đến bản chất là phải rõ như vậy.
Không như cái bài trên có hiểu rõ như vậy đâu mà chém mảng object này nọ
 
Upvote 0
mỗi phần tử của mảng Aray là cái nhà kho
Họ luống cuống đọc vội sợ bị mất phần đó anh. Viết bài nữa mà vẫn tự suy diễn.

---------
"mảng trong mảng" chỉ là con kiến thôi.
PHP:
Option Explicit

Sub vidu()
    Dim data As Variant, mang(1 To 3) As Variant, mang2 As Variant, mang3 As Variant, obj As Object
    Set obj = CreateObject("System.Collections.Hashtable")
    Range("A1").Value = "hello world!"
    data = Range("A1:D10").Value2
    obj.Add "skey1", "item1"
    obj.Add "skey2", data
    ReDim mang2(1 To 2)
    ReDim mang3(1 To 2)
    mang2(1) = "string"
    Set mang2(2) = obj
    mang3(1) = VBA.Array(1, 2, "abc")
    mang3(2) = mang2
   
    mang(1) = 1
    mang(2) = mang3
    Set mang(3) = ThisWorkbook
       
    MsgBox mang(2)(2)(2).Item("skey2")(1, 1)
    MsgBox mang(3).Worksheets(1).Range("A1").Value
End Sub
 
Upvote 0
Luống với chả cuống, bản chất mảng có thể chứa giá trị hoặc địa chỉ như bài 23 nói thôi ông ơi
 
Upvote 0
Ở bài #11 tôi có đề cập đến kiến thức "cao" và "sâu". Nhưng có lẽ tôi không giải thích hai từ ngữ này cho nên có bạn hiểu lầm.

Kiến thức sâu có nghĩa là hiểu rõ công cụ ấy làm việc như thế nào. Khi áp dụng tránh được sai lầm về ngữ pháp (lỗi VBA không chấp nhận code) và dữ liệu được truy xuất, xào nấu không bị sai sót (VBA chạy vo vo nhưng kết quả là một dấu chấm hỏi tổ bố).
Điển hình: biết rõ Evaluate chỉ hoạt động với biểu thức kiểu string, và parse cái string in hệt như hàm trên bảng tính thì mới áp dụng được ngữ pháp. Biết được [ ] là cái gì thì càng tốt. Nhiều người viết [a1] coi như là tiết kiệm 7 ký tự nhưng không hề biết [ ] là cái gì.

Kiến thức cao có nghĩa là biết rõ tính chất về hiệu quả của công cụ. Tức là biết lợi dụng tính chất để viết code dùng ít nguyên liệu (bộ nhớ và tốc độ).
Điển hình: biết mảng xếp các phần tử sát nhau thì biết rằng phương pháp lọc bằng chỉ số tuy giới hạn hơn container (như Dic...) nhưng dùng chỉ số (indice/indexes) nhanh hơn bảng băm (keys) một bậc.
 
Upvote 0
Mình thì không có khả năng moi xem trong VBE7.DLL cái array hoạt động như nào.
Còn thử nghiệm thực tế xem cái PHẦN TỬ mảng chứa cái gì... thì rất đơn giản: Xem RAM hoạt động thế nào.
- Nếu phần tử mảng là giá trị đơn thì khỏi bàn.
- Xét trường hợp object, Array.

Theo đồ thị RAM có 4 cái răng cưa.
Cái răng 0 là chép dữ liệu vào biến a.
Răng cưa 1-3 là chép a vào phần tử mảng b(i=1,2,3): Nó chép cả tảng a to tướng vào b(i) đó thôi.
Nói chung đọc cái gì thì cứ ---- đọc ---- chậm ---- từng ---- chữ ---- thôi.

1634635853387.png
 
Upvote 0
Không phải lúc nào cũng chép cả mớ hổ lốn tổ bố ấy vào được đâu, khi nào trình dịch chốt là inline thì mới như vậy.
Về bộ nhớ phải hỏi cái bác bài 27 ấy.

Chào nhé.
 
Upvote 0
Trước khì bảo không, giờ thì lại nói có.

Tưởng thế nào..

-0-0-0--0-0-0-
 
Upvote 0
Tưởng thế nào là "cái mảng chứa object" ấy ông ợ. Đọc kỹ lại cái bài 23 của cái bác @VetMini đi rồi hẵng chém.

Rách việc.
Nghỉ hẳn.
 
Upvote 0
Tới bài #29 là đủ hiểu rồi. Miễn thanh minh và níu kéo.

-0-0-0-
 
Upvote 0

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

Back
Top Bottom