câu lệnh target.row này sai ở đâu?

Liên hệ QC

Tường_Vi

Thành viên tiêu biểu
Tham gia
19/4/10
Bài viết
482
Được thích
121
Nghề nghiệp
Luôn tìm kiếm một vị trí tốt hơn
Học mảng - câu lệnh target.row này sai ở đâu?

PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
With Target
    Select Case .Column
    Case 1 or 2 or 3 or 4
    If .Value <> "" Then
        Range("F" & .Row) = Join(Range("A" & .Row & ":E" & .Row))
    End If
    End Select
End With
    
End Sub

Câu lệnh trên của em bị báo lỗi tại dòng bôi đen. Xin anh chị chỉ giúp

(em muốn nếu có sự thay đổi trong cột 1 hoặc 2 hoặc 3...thì sẽ nối range tương ứng vào cột F)
 
Lần chỉnh sửa cuối:
Code sai ở hàm Join.
Nhưng theo mình nên sửa như sau:

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
With Target
   If .Column < 5 And .Value <> "" Then
        Range("F" & .Row) = Join(WorksheetFunction.Transpose( _
        WorksheetFunction.Transpose(Range("A" & .Row & ":E" & .Row))), "")
    End If
End With
End Sub
 
Upvote 0
Nhìn thấy 2 hàm transpose lồng nhau như vậy lại đụng đến mảng 2 chiều về 1 chiều

Đợt này em quyết tâm nghiên cứu học về mảng

Cám ơn Anh
 
Upvote 0
Không phải mảng 2 chiều mà đích thị 1 chiều.
Hàm Join chỉ làm việc với mảng 1 chiều ngang chứ mảng 1 chiều dọc sinh chuyện. Và ta cũng không dùng được dạng Mg=Range(.....) vì như vậy lại thành mảng 2 chiều.
Vùng chọn dữ liệu đang là vùng ngang. Hàm Transpose chuyển cho ta vùng thành mảng nhưng nó lại thừa động tác ta không cần là đảo chiều mảng.
Vậy là phát sinh thêm 1 hàm để đảo từ mảng dọc thành mảng ngang.

Mình nôm na vậy chả hiểu văn phạm có đúng không.
 
Lần chỉnh sửa cuối:
Upvote 0
Không phải mảng 2 chiều mà đích thị 1 chiều.
Hàm Join chỉ làm việc với mảng 1 chiều ngang chứ mảng 1 chiều dọc sinh chuyện. Và ta cũng không dùng được dạng Mg=Range(.....) vì như vậy lại thành mảng 2 chiều.
Vùng chọn dữ liệu đang là vùng ngang. Hàm Transpose chuyển cho ta vùng thành mảng nhưng nó lại thừa động tác ta không cần là đảo chiều mảng.
Vậy là phát sinh thêm 1 hàm để đảo từ mảng dọc thành mảng ngang.

Mình nôm na vậy chả hiểu văn phạm có đúng không.
Thật ra gọi là mảng 1 chiều thì đơn giản chỉ là MẢNG 1 CHIỀU THÔI, chẳng dọc cũng chẳng ngang gì cả anh à
Còn Range với kích thước nhiều hơn 1 cell thì chỉ có thể <==> với mảng 2 chiều, cho dù Range ấy là 1 dòng nhiều cột hay 1 cột nhiều dòng
Hàm TRANSPOSE chẳng qua có 1 trường hợp đặc biệt khi dùng với Range nên khiến ta hiểu lầm: TRANSPOSE xoay mảng 90 đô, biến chiều thứ nhất thành chiều thứ 2 và ngược lại, nhưng đối với Range 1 cột nhiều dòng, qua hàm TRANSPOSE nó lại "bỏ" luôn chiều thứ 2 (vô tình qua biến đổi lại từ mảng 2 chiều trở thành 1 chiều)
---------------
Hic! Cái này thật ra cũng đã bàn rất nhiều lần trên diễn đàn rồi:
- Mảng là mảng còn Range là Range, 2 cái khác nhau hoàn toàn (dù có thể chuyển đổi qua lại)
- Mảng 1 chiều không bao giờ tương đương với bất cứ Range kiểu nào cả (vì Range chỉ có thể tương đương với mảng 2 chiều)
- Range và mảng 2 chiều có thể xem như mặt phẳng còn mảng 1 chiều thì lại giống như đường thẳng (khác nhau hoàn toàn về tính chất).. Và khi đã là đường thằng thì chỉ có 1 chiều duy nhất (là độ dài), đâu thể có chuyển dọc hay ngang
--------------------
Quay trở lại bài toán nối chuổi:
- Với dữ liệu ít, ta dùng hàm TRANSPOSE cũng không có vấn đề gì nhưng với dữ liệu lớn sẽ không ồn (vì hàm này có giới hạn)
- Tối ưu nhất là cứ việc biến Range thành mảng trước (mảng 2 chiều), xong, duyệt từng phần tử của mảng 2 chiều này và gán vào mảng 1 chiều mới ---> Cuối cùng, dùng Join với mảng 1 chiều vừa tạo ---> Đây mới phương pháp tối ưu về mặt tốc độ
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu như phương án của Ndu, khi duyệt ta nối luôn khỏi tạo mảng 1 chiều, khỏi Join phải không?
 
Upvote 0
Nếu như phương án của Ndu, khi duyệt ta nối luôn khỏi tạo mảng 1 chiều, khỏi Join phải không?
Cái đó cũng tùy anh à
Em không dám chắc rằng anh làm đến đâu nối đến đó sẽ nhanh hơn dùng Join đâu
(Vì thế mà em luôn chọn phương pháp dùng Join cho chắc, vì Join do MS viết)
 
Upvote 0
Ah... nói không có bằng chứng, thôi thì ta làm 1 cuộc thí nghiệm vậy:
- Thiết kế 1 bảng dữ liệu tùy ý từ A1 đến A60000
- Dùng 2 đoạn code dưới đây để kiểm tra tốc độ
PHP:
Sub Test1()
  Dim Arr(1 To 60000), i As Long, sArray, tmp As String, TG As Double
  TG = Timer
  sArray = Range("A1:A60000").Value
  For i = 1 To 60000
    tmp = tmp & ", " & sArray(i, 1)
  Next
  MsgBox Format(Timer - TG, "0.000000")
End Sub
PHP:
Sub Test2()
  Dim Arr(1 To 60000), i As Long, sArray, tmp As String, TG As Double
  TG = Timer
  sArray = Range("A1:A60000").Value
  For i = 1 To 60000
    Arr(i) = sArray(i, 1)
  Next
  tmp = Join(Arr, ", ")
  MsgBox Format(Timer - TG, "0.000000")
End Sub
Đoạn code 1 dùng phương pháp nối chuổi trực tiếp (duyệt đến đâu nối đến nấy)
Đoạn code 2 cho toàn bộ vào 1 mảng, xong việc nối chuổi 1 lần (dùng Join)
-----------------
Thí nghiệm xong sẽ thấy dùng Join nhanh hơn cả 100 lần so với cách thông thường
Từ đây, ta phải hết sức cẩn thận khi quyết định dùng các phương pháp nối chuổi
 
Upvote 0
Em hiểu các tài liệu và các vấn đề về mảng đã nói rất nhiều trên diễn đàn và chịu khó searh cũng sẽ ra được

Nhân tiện trên topic này, em xin được hỏi lại vì sau nhiều năm sử dụng excel em mới thấy được ý nghĩa và sự cần thiết phải học mảng

Đọc qua một số bài viết của anh NDU em hiểu
Join chỉ làm việc với mảng 1 chiều và (sử dụng Join để test mảng có là 1 chiều hay không?)

Với ví dụ trên:
PHP:
sArray = Range("A1:A60000").Value

Đoạn trên sArray là mảng 2 chiều phải không?

và thông qua vòng lặp FOR ...NEXT

PHP:
For i = 1 To 60000
    Arr(i) = sArray(i, 1)
Next

Giờ Arr(i) đã biến thành bảng 1 chiều?

Và em xin hỏi thêm
- Với cách khai báo không có As đằng sau thì biến được hiểu là Variant ạh?
- DIM Arr(1 To 60000)--> thì từ 1 đến 60.000 được hiểu là số hay là gi?
- Tại sao trước biến sArray là có một chữ s nhỏ --> ý nghĩa của chữ s này là gì?

Em cám ơn
 
Lần chỉnh sửa cuối:
Upvote 0
Và em xin hỏi thêm
- Với cách khai báo không có As đằng sau thì biến được hiểu là Variant ạh?
- DIM Arr(1 To 60000)--> thì từ 1 đến 60.000 được hiểu là số hay là gi?
- Tại sao trước biến sArray là có một chữ s nhỏ --> ý nghĩa của chữ s này là gì?

Em cám ơn
1> Đúng là vậy.. không nói gì có nghĩa là biến Variant
2> Dim Arr(1 to 60000): Khai báo biến Arr là mảng 1 chiều với 60000 phần tử và phần tử đầu được đánh số thứ tự = 1
Lưu ý: Nếu khai báo kiểu Dim Arr(60000) thì biến Arr sẽ có phần tử đầu được đánh số thứ tự 0... nó tương đương với Arr(0 to 60000) ---> vị chi nó có đến 60001 phần tử
- Về chữ s nhỏ ấy chẳng qua là thói quen của tôi (ý viết tắt của chữ SOURCE ---> là dữ liệu nguồn)
 
Upvote 0
Các bạn à, còn 1 cách để xác định chỉ số đầu tiên của mảng. Đó là Option base (0/1). Cũng như mọi thành phần khác VBA mặc định là Option Base 0. Ta cũng có thể thiết lập lại 1 lần và trong VBA sẽ hoat động theo Base này.

Ví dụ:

Mã:
Option Explicit
Option Base 1
Sub thu()
Dim Mg()
ReDim Mg(3)
Mg(1) = "A": Mg(2) = "B": Mg(3) = "C"
MsgBox Mg(1)
End Sub

Kết quả chạy Code là "A"
 
Upvote 0
Các bạn à, còn 1 cách để xác định chỉ số đầu tiên của mảng. Đó là Option base (0/1). Cũng như mọi thành phần khác VBA mặc định là Option Base 0. Ta cũng có thể thiết lập lại 1 lần và trong VBA sẽ hoat động theo Base này.

Ví dụ:

Mã:
Option Explicit
Option Base 1
Sub thu()
Dim Mg()
ReDim Mg(3)
Mg(1) = "A": Mg(2) = "B": Mg(3) = "C"
MsgBox Mg(1)
End Sub

Kết quả chạy Code là "A"
Xin lưu ý thêm rằng Option Base chỉ có tác dụng với mảng do ta tự mình tạo ra, hoàn toàn không có tác dụng với 1 mảng có sẵn hoặc 1 mảng được gán từ 1 mảng khác
Lấy vị dụ: Gán Range vào 1 biến, biến ấy có thể trở thành mảng nhưng Item đầu tiên luôn luôn được đánh số thứ tự = 1 (bất chấp việc ta có đặt Option Base 0 ở đầu code hay không)
 
Upvote 0
Web KT
Back
Top Bottom