- Tham gia
- 13/6/06
- Bài viết
- 4,737
- Được thích
- 10,243
- Giới tính
- Nam
- Nghề nghiệp
- Giáo viên, CEO tại Bluesofts
Đây là tình huống có vẽ đơn giản nhưng có nhiều vấn đề hửu ích để luyện tập viết code, nên mọi người mới trao đổi thêm với bạn để thấy rỏ hơn vấn đề, như nhiều lần bạn Vietmini nói tiêu chuẩn code hiệu quả không phải là ngắn nhất hay chạy nhanh nhất mà là cách giải quyết vấn đề rỏ ràng mạch lạc, các thành phần của code và toàn bộ code có thể kiểm soát được đầu vào và đầu ra, từ đó mới có khả năng lường hết các khả năng xảy ra, và khi cần điều chỉnh cũng sẽ dể dàng hơn.Bài này nói ăn may thì cũng không đúng lắm, thuật toán thì cũng hơi khó nhưng nó thuộc dạng toán đố, làm theo mẹo của câu đố này " Trong một cuộc đua 6 người , nếu người hạng 5 vượt qua người hạng 2 thì ông ta sẽ hạng mấy (before)"--"Khi người thứ hai bị người thứ ba vượt qua thì ông ta sẽ hạng mấy (after)". Các vị trí nếu đã sắp xếp đúng thì sắp xếp bao nhiêu lần nữa thì cũng vậy, những vị trí sai sẽ sắp xếp lại, em nghĩ trong bài này chỉ cần sắp 2 lần là được nếu để chắc ăn thì lên 100 lần, nếu dùng after thì có trường hợp 2 vị trí đầu sẽ sai, còn dùng before thì 2 trường hợp cuối sẽ sai vì vậy cùng cái code như trên thay after bằng before thì kết quả là như nhau. Đây là dạng bài toán sắp xếp chen ngang chứ không phải thay đổi vị trí, vì mỗi vòng lặp vị trí sẽ thay đổi. Bài dạng này ờ ngoài thực tế rất khó, cho dạng ban đầu rồi cho một kiểu sắp xếp sẵn , tìm số lần sắp xếp tối ưu nhất (ít nhất) (em đã từng đọc dạng bài này trong toán nâng cao lớp 5). Trong đây thì dùng vòng lặp để giải quyết , cư sắp xếp đến khi nào kết quả không đổi thì được vì vậy không phải là kết quả tối ưu.
Vâng, em sẽ chú ý chỗ này, làm bên công thức quen rồi, nên toàn ước đại thôi anh à, em còn phải học nhiều nữa!!!Đây là tình huống có vẽ đơn giản nhưng có nhiều vấn đề hửu ích để luyện tập viết code, nên mọi người mới trao đổi thêm với bạn để thấy rỏ hơn vấn đề, như nhiều lần bạn Vietmini nói tiêu chuẩn code hiệu quả không phải là ngắn nhất hay chạy nhanh nhất mà là cách giải quyết vấn đề rỏ ràng mạch lạc, các thành phần của code và toàn bộ code có thể kiểm soát được đầu vào và đầu ra, từ đó mới có khả năng lường hết các khả năng xảy ra, và khi cần điều chỉnh cũng sẽ dể dàng hơn.
Viết code, khó nhất là phải lường trước tất cả khả năng xảy ra và kiểm soát các khả năng nầy, khi mình còn nghi ngờ về một khả năng nào đó, đồng nghĩa code còn chưa hoàn chỉnh: "chỉ cần sắp 2 lần là được nếu để chắc ăn thì lên 100 lần"
Nếu bạn để ý thì sẽ thấy các công thức dùng tham chiếu vòng tôi không khuyến khích sử dụng. Làm chỉ mang tính chất nghiên cứu mà thôiEm chỉ đoán số vòng quay 2 là thấp nhấp thôi vì biết rằng từ 2 trở đi kết quả có thể không thay đổi nữa, còn xác định chính xác thì em chịu, ví dụ đơn giản gõ số 100 vào máy tính casio, hỏi là phải bấm căn 2 bao nhiêu lần để có kết quả là 1 với 5 chữ số thập phân, mình không thể biết được, nhưng với lập trình dùng Do while thì có thể chạy được số lần . Anh đã dùng interative caculation để làm bài toán dạng hồi quy, anh cho nó chạy vòng lặp xác định, vì đâu biết rằng đến khi nào nó cho kết quả không đổi!!!
Xếp kiểu này có trường hợp không đúng nha bạn.Néu ai có thuật toán mẹo gì thì tôi chưa biết. Chứ theo lô gic thuật toán "ăn chắc mặc bền" thì chỉ cần lập một mảng chứa tên tất cả các sheets theo thứ tự cần sắp xếp. Sau đó:
For i = 1 to Ubound(mang)-1
sheets(mang(i)).move before:=sheets(i)
Next i
Nếu muốn bẫy lỗi gì gì đó thì lúc sắp xếp cái mảng chứa tên sheets trên sẽ lòi ra.
Xếp kiểu này có trường hợp không đúng nha bạn.
Xin lỗi, tôi đọc không kỹ. Cách xếp bạn đưa ra là đúng rồi.Đó là lô gic tổng thể, nó chỉ có thể đúng hoặc không đúng. Không thể "có trường hợp không đúng"
' code sắp xếp tên sheet vào mảng theo thứ tự yêu cầu
' mảng sẽ xếp tên sheet theo thứ tự yêu cầu của chúng.
' Những sheets không có trong yêu cầu thì sẽ giữ lại vị trí TƯƠNG ĐỐI của chúng
Dim ordList() As String, reqList As Variant, staList as String
reqList = [range chứa yêu cầu] ' cột 1 chứa tên sheet, cột 2 chứa thứ tự yêu cầu
Redim ordList(1 to sheets.count)
for i = 1 to ubound(reqList)
ordList(reqList(i, 2)) = reqList(i, 1)
next i
staList = "," & Join(ordList, ",") & "," ' danh sách các sheets đã vào mảng
Dim lastBlank as integer
lastBlank = 1 ' đoán đại chỗ trống trong mảng sắp xếp, sẽ dò lại sau
for i = 1 to sheets.count ' định vị các sheets không có trong danh sách
if Instr(staList, "," & sheets(i).Name & ",") < 1 Then
For j = lastBlank to sheets.Count
if ordList(j) = "" Then ' chỗ này còn trống
ordList(j) = sheets(i).Name
lastBlank = j + 1
Exit For
End If
Next j
End If
next i
' đến đây thì ta có mảng ordList là mảng tên các sheets đã sắp xếp theo thứ tự yêu cầu
' code này nếu dùng ArrayList thì có thể nhanh và gọn hơn.
' code chỉ viết theo diễn giải thuật toán, chưa chạy thử
Excel cho phép dùng dấu phẩy (,) trong tên sheet nên khi kiểm tra trên chuỗi được nối bằng dấu phẩy (,) có thể xảy ra trường hợp ngoài mong muốn. Tôi nghĩ chỗ này nên dùng một ký tự mà Excel không cho phép dùng để đặt tên sheet.Vấn đề của tôi bây giờ là lập bảng sắp tên sheets. Nhất thời chưa nghĩ ra cách nào đặc sắc cho nên dùng kiểu rừng vậy
Mã:' code sắp xếp tên sheet vào mảng theo thứ tự yêu cầu ' mảng sẽ xếp tên sheet theo thứ tự yêu cầu của chúng. ' Những sheets không có trong yêu cầu thì sẽ giữ lại vị trí TƯƠNG ĐỐI của chúng Dim ordList() As String, reqList As Variant, staList as String reqList = [range chứa yêu cầu] ' cột 1 chứa tên sheet, cột 2 chứa thứ tự yêu cầu Redim ordList(1 to sheets.count) for i = 1 to ubound(reqList) ordList(reqList(i, 2)) = reqList(i, 1) next i staList = "," & Join(ordList, ",") & "," ' danh sách các sheets đã vào mảng Dim lastBlank as integer lastBlank = 1 ' đoán đại chỗ trống trong mảng sắp xếp, sẽ dò lại sau for i = 1 to sheets.count ' định vị các sheets không có trong danh sách if Instr(staList, "," & sheets(i).Name & ",") < 1 Then For j = lastBlank to sheets.Count if ordList(j) = "" Then ' chỗ này còn trống ordList(j) = sheets(i).Name lastBlank = j + 1 Exit For End If Next j End If next i ' đến đây thì ta có mảng ordList là mảng tên các sheets đã sắp xếp theo thứ tự yêu cầu ' code này nếu dùng ArrayList thì có thể nhanh và gọn hơn. ' code chỉ viết theo diễn giải thuật toán, chưa chạy thử
Cái này hay ở chỗ Ubound(mang)-1, vị trí cuối không cần sắp lại , vì khi các vị trí khác đã đúng thì tất nhiên vị trí cuối cùng cũng sẽ đúng luôn, ví sắp lại có thể dẫn đến bị sai, cám ơn anh!!!Néu ai có thuật toán mẹo gì thì tôi chưa biết. Chứ theo lô gic thuật toán "ăn chắc mặc bền" thì chỉ cần lập một mảng chứa tên tất cả các sheets theo thứ tự cần sắp xếp. Sau đó:
For i = 1 to Ubound(mang)-1
sheets(mang(i)).move before:=sheets(i)
Next i
Nếu muốn bẫy lỗi gì gì đó thì lúc sắp xếp cái mảng chứa tên sheets trên sẽ lòi ra.
Vâng cám ơn anh, em sẽ để ý chỗ này!!!Nếu bạn để ý thì sẽ thấy các công thức dùng tham chiếu vòng tôi không khuyến khích sử dụng. Làm chỉ mang tính chất nghiên cứu mà thôi
Ví dụ căn 2 mà bạn đưa ra. Sử dụng vòng lặp Do... While, trong đó thực hiện phép tính căn và kiểm tra kết quả là một giải pháp hoàn toàn phù hợp vì khi thoát vòng lặp bạn sẽ biết chắc chắn bài toán đưa ra có nghiệm hay không. Nếu có thì nghiệm là bao nhiêu.
Quay lại bài sắp xếp này, bạn cũng có thể dùng vòng lặp với bao nhiêu vòng tùy ý nhưng phải đảm bảo sau khi chạy macro các sheet chắc chắn đã được sắp xếp theo yêu cầu đưa ra. Có thể làm như trên là đưa vào Do... While và kiểm tra (kiểm tra sự thay đổi, đối chiếu với thứ tự cần sắp xếp)
Không phải vậy đâu bạn, không -1 cũng không thể sai vì vòng lặp duyệt các sheet theo thứ tự mà yêu cầu đặt ra (mảng đã sắp xếp) nên xếp đến sheet nào thì sheet đó đã ở đúng vị trí của nó (không chen ngang). Việc xếp sheet cuối vào vị trí cuối là không cần thiết mà thôi.Cái này hay ở chỗ Ubound(mang)-1, vị trí cuối không cần sắp lại , vì khi các vị trí khác đã đúng thì tất nhiên vị trí cuối cùng cũng sẽ đúng luôn, ví sắp lại có thể dẫn đến bị sai, cám ơn anh!!!
Bạn nghĩ xem cái này là do ai?Đoạn code mọi người cho ở trên em chạy trên file VD làm ví dụ thì OK lắm nhưng khi chạy trên file thực tế cần làm thì nó lại chạy không ra thứ tự gì.