Tạo danh sách phòng thi theo dữ liệu có sẵn

Liên hệ QC

caosonkt

Thành viên mới
Tham gia
27/4/10
Bài viết
6
Được thích
1
Chào anh chị! Em là thành viên mới, xin hỏi anh chị một vấn đề như sau:

Em có Sheet dữ liệu đã nhập, nay muốn từ dữ liệu này tạo ra danh sách phòng thi theo mẫu có sẵn (file kèm theo) bằng cách nhấn một nút lệnh hoặc có hàm sử lý. Yêu cầu đặt ra là: mỗi phòng thi chỉ gồm 24 thí sinh, ta sẽ tạo n phòng thi như vậy. Cuối cùng, nếu số lượng thí sinh <= 28 thì tạo 01 phòng thi, nếu > 28 thì chia làm 02 phòng thi. Mong anh chị giúp đỡ.
 

File đính kèm

  • ChiaPhongThi.xls
    49.5 KB · Đọc: 47
Chào anh chị! Em là thành viên mới, xin hỏi anh chị một vấn đề như sau:

Em có Sheet dữ liệu đã nhập, nay muốn từ dữ liệu này tạo ra danh sách phòng thi theo mẫu có sẵn (file kèm theo) bằng cách nhấn một nút lệnh hoặc có hàm sử lý. Yêu cầu đặt ra là: mỗi phòng thi chỉ gồm 24 thí sinh, ta sẽ tạo n phòng thi như vậy. Cuối cùng, nếu số lượng thí sinh <= 28 thì tạo 01 phòng thi, nếu > 28 thì chia làm 02 phòng thi. Mong anh chị giúp đỡ.
Bạn có thể tham khảo link sau http://www.giaiphapexcel.com/forum/showthread.php?24687-Chia-danh-s%C3%A1ch-ph%C3%B2ng-thi
Hoặc http://www.giaiphapexcel.com/forum/...ự-theo-số-lượng-nhất-định&p=233236#post233236
chúc vui
 
Lần chỉnh sửa cuối:
Cảm ơn các bác đã chỉ giáo, nhưng em muốn là từ dữ liệu đó ví dụ ta có nút lệnh "tạo phòng thi" khi nhấn sẽ tự động tạo ra trên mỗi sheet một phòng thi cho đến khi hết danh sách thỏa mãn yêu cầu đã nêu.
 
Bạn xem thêm trong file & tự tạo nút lệnh cho macro, nghen.

Mã:
Option Explicit
[B]Sub ChiaPhongThi()[/B]
 Dim eRw As Long, SoDu As Byte, SoFong As Byte, Con As Byte, Jj As Byte
 Dim Sh As Worksheet, TDe As Range
 
 Sheets("ChiaPhongThi").Select:        Set Sh = Sheets("Mau")
 Set TDe = Sh.[a4].Resize(25, 7)
 eRw = [A65500].End(xlUp).Row - 1
 SoDu = eRw Mod 24:                    Sh.Columns("i:iV").ClearContents
 SoFong = IIf(SoDu < 4, 0, 1) + eRw \ 24
 
 For Jj = 1 To SoFong
   Sh.Cells(4, 8 * Jj - 7).Resize(25, 7).Value = TDe.Value
   If SoDu < 4 And Jj = SoFong Then Con = 4
   Sh.Cells(5, 8 * Jj - 6).Resize(24 + Con, 6).Value = _
      Cells((Jj - 1) * 24 + 2, "B").Resize(24 + Con, 6).Value
 Next Jj
[B]End Sub[/B]
 

File đính kèm

  • GPE.rar
    18.3 KB · Đọc: 42
Lần chỉnh sửa cuối:
Em cũng xin tham gia 1 code cho thư giãn.
Lâu lâu mới viết code, thấy dài mà thế nào.
Tính làm thêm 1 cột phụ dùng int và mode tạo số phòng, sau đó dùng match, countif chép qua từng sh. Chưa biết có khoa học hơn.
PHP:
Option Explicit
Dim FRow As Long
Dim rngData As Range, PhName As String
Dim soPh As Long, iP As Long, endR As Long, SoTS As Long, SoDu As Long
Dim SoTSph As Long
Sub ChiaPhongThi()
FRow = 5
SoTSph = 24
With Application
  .ScreenUpdating = False: .Calculation = xlCalculationManual
  .DisplayAlerts = False
End With
Sheets("ChiaPhongThi").Select
xoash
With Sheets("ChiaPhongThi")
  endR = .Cells(65000, 2).End(xlUp).Row 'cot ten hs'
  SoTS = endR - 1
  
End With
soPh = Int(SoTS / SoTSph)
If SoTS Mod SoTSph < 4 Then
  soPh = soPh
  If SoTS Mod SoTSph > 0 Then
    SoDu = SoTS Mod SoTSph
  End If
Else
  soPh = soPh + 1
End If
Set rngData = Range("A2:K" & endR)
For iP = 1 To soPh
  If iP Mod 20 = 0 Then ActiveWorkbook.Save
  If SoDu <> 0 Then
    PhName = "Ph" & Right("00" & iP, 3)
    Sheets("Mau").Copy after:=Sheets("Mau")
      With ActiveSheet
        .Name = PhName
        If iP < soPh Then
          .Range("B" & FRow & ":F" & FRow + SoTSph - 1).Value = rngData.Offset(SoTSph * (iP - 1), 1).Resize(SoTSph, 5).Value
          .Range("G" & FRow & ":G" & FRow + SoTSph - 1).Value = rngData.Offset(SoTSph * (iP - 1), 10).Resize(SoTSph, 1).Value
        Else
          .Range("B" & FRow & ":F" & FRow + SoTSph - 1 + SoDu).Value = rngData.Offset(SoTSph * (iP - 1), 1).Resize(SoTSph + SoDu, 5).Value
          .Range("G" & FRow & ":G" & FRow + SoTSph - 1 + SoDu).Value = rngData.Offset(SoTSph * (iP - 1), 10).Resize(SoTSph + SoDu, 1).Value
          'tao so tt lai
          With .Range("A" & FRow & ":A28")
            .ClearContents
          End With
          With .Range("A" & FRow & ":A" & FRow + SoTSph + SoDu - 1)
            .FormulaR1C1 = "=ROW()-4"
            .Value = .Value
          End With
        End If
      End With
  End If
Next
Set rngData = Nothing
With Application
  .ScreenUpdating = True: .Calculation = xlCalculationAutomatic
  .DisplayAlerts = True
End With
End Sub
Sub xoash()
Dim Sh As Worksheet
For Each Sh In Worksheets
  If Left(Sh.Name, 2) = "Ph" Then Sh.Delete
Next
End Sub
 
Xin hỏi chi tiết hơn một chút

Em cảm ơn các bác nhiều, em thấy ý tưởng bác ThuNghi hay đó. Em gửi kèm theo file này các bác tư vấn giúp với. Em chỉ xem code của các bác và cố gắng chỉnh sửa theo thôi chứ chưa có thể làm từ đầu được. Các bác chỉ giúp em nhé, em đang cố gắng học hỏi.
 

File đính kèm

  • ChiaPhongThi.xls
    89 KB · Đọc: 18
Bạn hãy cho biết mục đích của việc bỏ danh sách thí sinh của mỗi fòng thi lên 1 trang tính để làm gì vậy?

Nếu để in ra thì không nhất thiết fải vậy

Nếu không cần sao trộn thí sinh thì ta có thể không cần đến cả trang tính thứ 2, mà chỉ cần thêm vô danh sách HS đó 1 cột chứa mã fòng thi để bố trí thí sinh là xong;

Khi cần ta sẽ lọc ra & đem in hay làm thứ gì khác.
 
Mục đích của em ngoài danh sách phòng thi như trên, dựa vào code các bác cho em sẽ tạo thêm một số danh sách khác nữa như BB giao nhận bài thi, bảng ghi kết quả... Do vậy em rất cần đoạn code thỏa mãn yêu cầu có lựa chọn cột cần chèn vào trong biểu mẫu. Ví dụ như nếu danh sách khác có chèn cột trường dự thi, TBC lớp 9... Em thiết kế sheet DLGoc ghi tất cả các thông tin của học sinh để từ đó trích xuất sang các biểu mẫu khác nhau. Các anh chị giúp em nhé.
 
Chia fòng ngay trên trang 'ChìaongThi'

Bằng macro như sau:

PHP:
Option Explicit
Sub FanFongThi()
 Const ChuA As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 Dim Rng As Range, Clls As Range
 Dim SoTS As Integer, SoDu As Byte, SoFong As Byte, Con As Byte, jJ As Byte
 
 Sheets("ChiaPhongThi").Select:              SoTS = [a65500].End(xlUp).Row
 Set Rng = [l1]:                             [l1].Value = "FongThi"
 SoFong = 1
 For jJ = 2 To SoTS
   Con = Con + 1
   Cells(jJ, "L").Value = Mid(ChuA, SoFong, 1)
   If SoTS - jJ < 5 And Con = 24 Then
      Cells(jJ + 1, "L").Resize(SoTS - jJ).Value = Mid(ChuA, SoFong, 1)
      Exit For
   End If
   If Con = 24 Then
      SoFong = SoFong + 1:    Con = 0
   End If
 Next jJ
End Sub
 
Chào anh chị! Em là thành viên mới, xin hỏi anh chị một vấn đề như sau:

Em có Sheet dữ liệu đã nhập, nay muốn từ dữ liệu này tạo ra danh sách phòng thi theo mẫu có sẵn (file kèm theo) bằng cách nhấn một nút lệnh hoặc có hàm sử lý. Yêu cầu đặt ra là: mỗi phòng thi chỉ gồm 24 thí sinh, ta sẽ tạo n phòng thi như vậy. Cuối cùng, nếu số lượng thí sinh <= 28 thì tạo 01 phòng thi, nếu > 28 thì chia làm 02 phòng thi. Mong anh chị giúp đỡ.

Thử chia phòng ngay tại danh sách gốc, nếu đúng ta lại làm tiếp.
PHP:
Sub Chia()
Application.ScreenUpdating = False
On Error Resume Next
With Sheets("chiaPhongThi")
    .[b2:b500].SpecialCells(4).EntireRow.Delete
    For n = 1 To 100
        With .[b2:b500].SpecialCells(2)
            For i = 1 To .Areas.Count
                If .Areas(i)(25) > 0 Then .Areas(i)(25).EntireRow.Insert
            Next
                If Range(.Areas(.Areas.Count - 1), .Areas(.Areas.Count)).Rows.Count < 48 Then
                  Range(.Areas(.Areas.Count - 1), .Areas(.Areas.Count)).SpecialCells(4).EntireRow.Delete
                End If
        End With
    Next
    With .[b2:b500].SpecialCells(2)
        .Areas(.Areas.Count)((.Areas(.Areas.Count).Rows.Count) / 2).EntireRow.Insert
    End With
End With
End Sub
 

File đính kèm

  • ChiaPhongThi.xls
    64 KB · Đọc: 24
Thử chia phòng ngay tại danh sách gốc, nếu đúng ta lại làm tiếp.
PHP:
Sub Chia()
Application.ScreenUpdating = False
On Error Resume Next
With Sheets("chiaPhongThi")
    .[b2:b500].SpecialCells(4).EntireRow.Delete
    For n = 1 To 100
        With .[b2:b500].SpecialCells(2)
            For i = 1 To .Areas.Count
                If .Areas(i)(25) > 0 Then .Areas(i)(25).EntireRow.Insert
            Next
                If Range(.Areas(.Areas.Count - 1), .Areas(.Areas.Count)).Rows.Count < 48 Then
                  Range(.Areas(.Areas.Count - 1), .Areas(.Areas.Count)).SpecialCells(4).EntireRow.Delete
                End If
        End With
    Next
    With .[b2:b500].SpecialCells(2)
        .Areas(.Areas.Count)((.Areas(.Areas.Count).Rows.Count) / 2).EntireRow.Insert
    End With
End With
End Sub
Em nghĩ chỉ cần 1 vòng lập là đủ
PHP:
Sub Main(SrcRng As Range, NoP As Long)
  Dim i As Long, TmpRng As Range
  Application.ScreenUpdating = False
  On Error Resume Next
  If SrcRng.Rows.Count > NoP Then
    With SrcRng
      Set TmpRng = .Rows(NoP + 1)
      For i = NoP + 1 To .Rows.Count Step NoP
        Set TmpRng = Union(TmpRng, .Rows(i))
      Next
    End With
    TmpRng.Insert 2
  End If
  Application.ScreenUpdating = True
End Sub
Để chạy code này, ta viết 1 đoạn code nữa
PHP:
Sub Chia()
  Main Sheets("ChiaPhongThi").Range("A2:K192"), 24
End Sub
Các đối số:
- SrcRng là vùng dữ liệu gốc
- NoP là số lượng thí sinh có trong 1 phòng
Code trên dùng vòng lập "thu gom" các cell thỏa điều kiện, đến cuối cùng mới Insert 1 lần, như vậy tốc độ sẽ rất nhanh (nhanh hơn kiểu dò đến đâu chèn dòng đến nấy)
Ngoài ra, em insert theo kiểu Shift Cells down nên hoàn toàn không ảnh hưởng đến những vùng khác
Bài này em nghĩ thậm chí có thể không cần vòng lập luôn (nếu biết khéo léo xử lý Range)
 

File đính kèm

  • ChiaPhongThi.rar
    16.3 KB · Đọc: 37
1. "thu gom" các cell thỏa điều kiện, đến cuối cùng... làm gì mới làm -> Hôm nay mới học được chiêu này.
2. Tôi chưa hiểu cách viết code như dạng Sub Main(SrcRng As Range, NoP As Long)
Trong trường hợp nào viết code dạng
PHP:
Sub abc(các kiểu biến)
...
End sub
Trường hợp nào viết code dạng
PHP:
Sub abc()
Dim...
...
End sub
Nhờ các bạn giải thích giúp. Thanks !
 
2. Tôi chưa hiểu cách viết code như dạng Sub Main(SrcRng As Range, NoP As Long)
Trong trường hợp nào viết code dạng
PHP:
Sub abc(các kiểu biến)
...
End sub
Trường hợp nào viết code dạng
PHP:
Sub abc()
Dim...
...
End sub
Nhờ các bạn giải thích giúp. Thanks !
Sub có tham số truyền cũng giống y chang như Sub thường thôi mà anh ---> Nó chẳng qua như 1 bộ đã được setup sẳn, đến khi cần thì "nhấn nút" là chạy thôi
Sub Main ở trên nếu được viết theo cách thông thường (không có tham số truyền) thì sẽ như thế này:
PHP:
Sub Main()
  Dim SrcRng As Range, NoP As Long
  Dim i As Long, TmpRng As Range
  Application.ScreenUpdating = False
  On Error Resume Next
  Set SrcRng = Sheets("ChiaPhongThi").Range("A2:K192")
  NoP = 24
  If SrcRng.Rows.Count > NoP Then
    With SrcRng
      Set TmpRng = .Rows(NoP + 1)
      For i = NoP + 1 To .Rows.Count Step NoP
        Set TmpRng = Union(TmpRng, .Rows(i))
      Next
    End With
    TmpRng.Insert 2
  End If
  Application.ScreenUpdating = True
End Sub
Giờ ta cho 2 biến SrcRngNoP vào làm tham số của Sub, để đến khi cần chạy ta có thể tùy biến 2 tham số này 1 cách thoải mái ---> Và đây chính là mục đích chính!
Anh cứ tưởng tưởng nếu viết theo cách thông thường, mỗi khi cần thay đổi vùng dữ liệu, thay đổi số lượng thí sinh trong 1 phòng thì anh sẽ.. cực hơn, đúng không?
 
Lần chỉnh sửa cuối:
Web KT

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

Back
Top Bottom