Sắp xếp các Sheet - Bài toán sắp xếp

Liên hệ QC

Nguyễn Duy Tuân

Nghị Hách
Thành viên danh dự
Tham gia
13/6/06
Bài viết
4,649
Được thích
10,138
Giới tính
Nam
Nghề nghiệp
Giáo viên, CEO tại Bluesofts
Gửi các bạn phương pháp sắp xếp các Sheet trong Workbook theo thứ tự nào đó.
 

File đính kèm

  • Sapxep.zip
    14.8 KB · Đọc: 2,752
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.
Đâ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"
 
Upvote 0
Đâ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"
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!!!
 
Upvote 0
Em 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!!!
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)
 
Upvote 0
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.
 
Upvote 0
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.
 
Upvote 0
Đó 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"
Xin lỗi, tôi đọc không kỹ. Cách xếp bạn đưa ra là đúng rồi.

Tôi nói có trường hợp không đúng là đang nói đến từng trường hợp cụ thể, giống như code đầu tiên của bạn eke_rula có khi kết quả đúng có khi kết quả sai tùy vào từng trường hợp cụ thể.
Và đương nhiên khi đã có trường hợp không đúng thì thuật toán / cách làm đó sai.
 
Upvote 0
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ử
 
Upvote 0
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ử
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.
 
Upvote 0
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.
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!!!
 
Upvote 0
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)
Vâng cám ơn anh, em sẽ để ý chỗ này!!!
 
Upvote 0
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!!!
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.
 
Upvote 0
Bấm trả lời tự nhiên thấy trích dẫn mấy dấu gạch. Tưởng bấm nhầm bấm lại vẫn thế :).
 
Upvote 0
Cảm ơn các bác đã tham gia giúp đỡ rất nhiều, nhưng em coppy các code về chạy thử vẫn không được như ý muốn. Giờ em tải chính file em đang làm lên các bác giúp em nhé.
Mục lục tại sheet index, em muốn nó sắp xếp các sheet theo thứ tự cho trước như ở cột A:B. Mong các bác giúp đỡ, em cảm ơn nhiều!!!!
 

File đính kèm

  • NHAT KY EP COC.rar
    3 MB · Đọc: 23
Upvote 0
Tiêu đề bạn hỏi à "bài toán..." tôi tưởng bạn muốn hỏi thuật toán rồi tự code lấy.
Ai biết đâu bạn muốn xin code từ a đến z. Lần sau nói thẳng "nhờ code giùm"
Chờ mấy bạn kia đi nhé. Thuật toán thì tôi có hứng chứ viết code từ a đến z thì tôi lười lắm.
 
Upvote 0
Đ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ì. Bác VietMini nói thế thành ra chả ai giúp em. Thực ra e mới biết sử dụng macro thôi chứ để viết ra nó thì em chưa biết. Chắc là bác thấy file em gửi lên có macro ở trong nên bác nghĩ em biết mà không chịu làm lại đi nhờ người khác phải không ạ. Huhu em chưa biết thuật toán trong đó là gì ạ. Mong các bác biết thông thạo rồi thì bớt chút thời gian giúp em vì em đang cần gấp, sau này em sẽ cố gắng học.
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom