'***************************************************************************************************
' 「席替え」処理(乱数を使って再配置します。) Module1(Module)
'
' 作成者:井上治 URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev 変更履歴内容------------------------------------------------------------------------>
'05/11/14(1.00)新規作成
'12/03/26(1.01)修正等
'20/03/02(1.10)*.xlsm化、他
'***************************************************************************************************
Option Explicit
'===================================================================================================
' テスト用スイッチ(1か0かを書き換えて動作させて下さい)
#Const cnsTEST = 0 ' ← 1=テスト(出席番号順), 0=本番(乱数により席替え)
'---------------------------------------------------------------------------------------------------
Public Const g_cnsSH1 As String = "座席表"
Public Const g_cnsSH2 As String = "在籍名簿"
Public Const g_cnsCntMidashi As Long = 1 ' 在籍名簿の見出し行数
'***************************************************************************************************
' ■■■ ワークシート側からの呼び出し処理 ■■■
'***************************************************************************************************
'* 処理名 :SEKIGAE
'* 機能 :「席替え」処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数 :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2005年11月14日
'* 作成者 :井上 治
'* 更新日 :2020年03月02日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Sub SEKIGAE()
'-----------------------------------------------------------------------------------------------
Dim objSh1 As Worksheet ' 座席表シート
Dim objSh2 As Worksheet ' 在籍名簿シート
Dim objR As Range ' セル
Dim lngRow As Long ' 行INDEX
Dim lngRow2 As Long ' 行INDEX
Dim lngRowMin As Long ' 名簿先頭行
Dim lngRowMax As Long ' 名簿最終行
Set objSh1 = ThisWorkbook.Worksheets(g_cnsSH1)
Set objSh2 = ThisWorkbook.Worksheets(g_cnsSH2)
'---------------------------------------------------------------------------
' インデックス範囲と配列初期化
lngRowMin = g_cnsCntMidashi + 1
' 在籍名簿シート
With objSh2
' フィルタ解除
If .FilterMode Then .ShowAllData
' 有効最終行の取得
lngRowMax = .Range("$A$" & .Rows.Count).End(xlUp).Row
End With
lngRow2 = lngRowMin
'---------------------------------------------------------------------------
' 乱数生成
Randomize
' 座席表シートの使用領域をループ
For Each objR In objSh1.UsedRange
' 非ロックセルを対象とする(生徒の机)
If Not objR.Locked Then
' ランダム番号発生
#If cnsTEST <> 1 Then
lngRow = FP_GET_NO(lngRow2, lngRowMin, lngRowMax)
#Else
lngRow = lngRow2
#End If
' セルに出席番号と氏名をセット
objR.Value = Format(objSh2.Cells(lngRow, 1).Value, "000") & vbLf & _
objSh2.Cells(lngRow, 2).Value
' 次の行へ
lngRow2 = lngRow2 + 1
If lngRow2 > lngRowMax Then Exit For
End If
Next objR
'---------------------------------------------------------------------------
ThisWorkbook.Saved = True ' 一応、上書き保存不要としておきます。
End Sub
'***************************************************************************************************
' ■■■ サブ処理(Private) ■■■
'***************************************************************************************************
'* 処理名 :FP_GET_NO
'* 機能 :ランダム番号発生
'---------------------------------------------------------------------------------------------------
'* 返り値 :生成したランダム番号(Long)
'* 引数 :Arg1 = 現在の生成位置(Long) ※実際は在籍名簿シートの現在行
'* Arg2 = 最小生成番号(Long)
'* Arg3 = 最大生成番号(Long)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2005年11月14日
'* 作成者 :井上 治
'* 更新日 :2020年03月02日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Function FP_GET_NO(ByVal lngIx As Long, _
ByVal lngLowerBound As Long, _
ByVal lngUpperBound As Long) As Long
'-----------------------------------------------------------------------------------------------
Static tblNo() As Long ' 番号重複判定用配列(Static)
Dim lngIx2 As Long ' テーブルINDEX(Work)
Dim lngNo As Long ' 採番値
Dim blnSuccess As Boolean ' 採番成功判定
'---------------------------------------------------------------------------
' 先頭INDEX値の場合は配列を作成(初期化)
If lngIx = lngLowerBound Then ReDim tblNo(lngLowerBound To lngUpperBound)
'---------------------------------------------------------------------------
' 採番成功まで繰り返す
Do Until blnSuccess
' 乱数の発生
lngNo = Int((lngUpperBound - lngLowerBound + 1) * Rnd + lngLowerBound)
blnSuccess = True
lngIx2 = lngLowerBound
' 念のため既に使った番号でないことを確認
Do While lngIx2 < lngIx
' 既に発番されている場合は再発番させる
If tblNo(lngIx2) = lngNo Then
blnSuccess = False
Exit Do
End If
' 次へ
lngIx2 = lngIx2 + 1
Loop
Loop
'---------------------------------------------------------------------------
' 採番値を返す
tblNo(lngIx) = lngNo
FP_GET_NO = lngNo
End Function
'----------------------------------------<< End of Source >>----------------------------------------
'***************************************************************************************************
' 「席替え」処理2(乱数を使って再配置します。) Module1(Module)
'
' 作成者:井上治 URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev 変更履歴内容------------------------------------------------------------------------>
'05/11/14(1.00)新規作成
'12/03/26(1.01)修正等
'20/03/02(1.10)*.xlsm化、他
'***************************************************************************************************
Option Explicit
'===================================================================================================
' テスト用スイッチ(1か0かを書き換えて動作させて下さい)
#Const cnsTEST = 0 ' ← 1=テスト(出席番号順), 0=本番(乱数により席替え)
'---------------------------------------------------------------------------------------------------
Public Const g_cnsSH1 As String = "座席表"
Public Const g_cnsSH2 As String = "在籍名簿"
Public Const g_cnsCntMidashi As Long = 1 ' 在籍名簿の見出し行数
'***************************************************************************************************
' ■■■ ワークシート側からの呼び出し処理 ■■■
'***************************************************************************************************
'* 処理名 :SEKIGAE
'* 機能 :「席替え」処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数 :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2005年11月14日
'* 作成者 :井上 治
'* 更新日 :2020年03月02日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Sub SEKIGAE()
'-----------------------------------------------------------------------------------------------
Dim objSh1 As Worksheet ' 座席表シート
Dim objSh2 As Worksheet ' 在籍名簿シート
Dim objR As Range ' セル
Dim lngRow As Long ' 行INDEX
Dim lngRow2 As Long ' 行INDEX
Dim lngRowMin As Long ' 名簿先頭行
Dim lngRowMax As Long ' 名簿最終行
Dim tblRow As Variant ' 行番号テーブル
Set objSh1 = ThisWorkbook.Worksheets(g_cnsSH1)
Set objSh2 = ThisWorkbook.Worksheets(g_cnsSH2)
'---------------------------------------------------------------------------
' インデックス範囲と配列初期化
lngRowMin = g_cnsCntMidashi + 1
lngRowMax = objSh2.Range("A65536").End(xlUp).Row
lngRow2 = lngRowMin
'---------------------------------------------------------------------------
' 並べ替え処理を呼び出す(配列で結果受け取り)
tblRow = FP_GET_NO2(lngRowMin, lngRowMax)
'---------------------------------------------------------------------------
' 座席表シートの使用領域をループ
For Each objR In objSh1.UsedRange
' 非ロックセルを対象とする
If Not objR.Locked Then
' テーブルから行を受け取る
#If cnsTEST <> 1 Then
lngRow = tblRow(lngRow2) ' 乱数処理の結果の行
#Else
lngRow = lngRow2 ' こちらは在籍表通り
#End If
' セルに出席番号と氏名をセット
objR.Value = Format(objSh2.Cells(lngRow, 1).Value, "000") & vbLf & _
objSh2.Cells(lngRow, 2).Value
' 次の行へ
lngRow2 = lngRow2 + 1
If lngRow2 > lngRowMax Then Exit For
End If
Next objR
'---------------------------------------------------------------------------
ThisWorkbook.Saved = True ' 一応、上書き保存不要としておきます。
End Sub
'***************************************************************************************************
' ■■■ サブ処理(Private) ■■■
'***************************************************************************************************
'* 処理名 :FP_GET_NO2
'* 機能 :ランダム番号発生2
'---------------------------------------------------------------------------------------------------
'* 返り値 :生成したランダム番号テーブル(Array:Long⇒Variant)
'* 引数 :Arg1 = 最小生成番号(Long)
'* Arg2 = 最大生成番号(Long)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2005年11月14日
'* 作成者 :井上 治
'* 更新日 :2020年03月02日
'* 更新者 :井上 治
'* 機能説明:LowerBoundからUpperBoundまでの要素の整数の配列を返す
'* 注意事項:
'***************************************************************************************************
Private Function FP_GET_NO2(lngLowerBound As Long, lngUpperBound As Long) As Variant
'-----------------------------------------------------------------------------------------------
Dim lngIx As Long ' テーブルINDEX
Dim lngIx2 As Long ' テーブルINDEX
Dim tmpNo As Long ' 並替えWORK
Dim tmpSng As Single ' 並替えWORK
Dim tblNo() As Long ' ランダム番号テーブル
Dim tblSng() As Single ' 乱数テーブル
'---------------------------------------------------------------------------
' 配列を指定要素数で初期化
ReDim tblNo(lngLowerBound To lngUpperBound)
ReDim tblSng(lngLowerBound To lngUpperBound)
'---------------------------------------------------------------------------
' 乱数生成
Randomize
' tblNoに整数の連番を設定,tblSngには乱数を設定
For lngIx = lngLowerBound To lngUpperBound
tblNo(lngIx) = lngIx
tblSng(lngIx) = Rnd()
Next lngIx
'---------------------------------------------------------------------------
' バブルSORT(件数が少ないので)
lngIx = lngLowerBound
Do While lngIx < lngUpperBound
lngIx2 = lngUpperBound
Do While lngIx2 > lngIx
If tblSng(lngIx2) < tblSng(lngIx) Then
tmpSng = tblSng(lngIx)
tblSng(lngIx) = tblSng(lngIx2)
tblSng(lngIx2) = tmpSng
tmpNo = tblNo(lngIx)
tblNo(lngIx) = tblNo(lngIx2)
tblNo(lngIx2) = tmpNo
End If
lngIx2 = lngIx2 - 1
Loop
lngIx = lngIx + 1
Loop
'---------------------------------------------------------------------------
' 結果の配列(整数の方)を返す
FP_GET_NO2 = tblNo
End Function
'----------------------------------------<< End of Source >>----------------------------------------
'***************************************************************************************************
'* 処理名 :SEKIGAE2
'* 機能 :「席替え」処理② ※ご参考に1机ごとに動作
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数 :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2005年11月14日
'* 作成者 :井上 治
'* 更新日 :2020年03月02日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Sub SEKIGAE2()
'-----------------------------------------------------------------------------------------------
Dim objSh1 As Worksheet ' 座席表シート
Dim objSh2 As Worksheet ' 在籍名簿シート
Dim objR As Range ' セル
Static lngRow2 As Long ' 行INDEX
Static lngRowMin As Long ' 名簿先頭行
Static lngRowMax As Long ' 名簿最終行
Static tblR() As String ' セルアドレステーブル
Static tblRow As Variant ' 行番号テーブル
Dim lngRow As Long ' 行INDEX
Set objSh1 = ThisWorkbook.Worksheets(g_cnsSH1)
Set objSh2 = ThisWorkbook.Worksheets(g_cnsSH2)
'---------------------------------------------------------------------------
' インデックス範囲と配列初期化
If ((lngRow2 = 0) Or (lngRow2 > lngRowMax)) Then
lngRowMin = g_cnsCntMidashi + 1
lngRowMax = objSh2.Range("A65536").End(xlUp).Row
ReDim tblR(lngRowMin To lngRowMax)
lngRow = lngRowMin
' 座席表シートの使用領域をループ
For Each objR In objSh1.UsedRange
' 非ロックセルを対象とする
If objR.Locked <> True Then
If lngRow > lngRowMax Then ReDim Preserve tblR(lngRow)
tblR(lngRow) = objR.Address
objR.ClearContents
lngRow = lngRow + 1
End If
Next objR
' 並べ替え処理を呼び出す(配列で結果受け取り)
tblRow = FP_GET_NO2(lngRowMin, lngRowMax)
' 先頭行をセット
lngRow2 = lngRowMin
End If
'---------------------------------------------------------------------------
' テーブルから行を受け取る
#If cnsTEST <> 1 Then
lngRow = tblRow(lngRow2) ' 乱数処理の結果の行
#Else
lngRow = lngRow2 ' こちらは在籍表通り
#End If
'---------------------------------------------------------------------------
' セルに出席番号と氏名をセット
objSh1.Range(tblR(lngRowMin)).Value = _
Format(objSh2.Cells(lngRow, 1).Value, "000") & vbLf & _
objSh2.Cells(lngRow, 2).Value
lngRow2 = lngRow2 + 1
'---------------------------------------------------------------------------
ThisWorkbook.Saved = True ' 一応、上書き保存不要としておきます。
End Sub
'***************************************************************************************************
' 「席替え」処理(乱数を使って再配置します。) Module2(Module)
'
' 作成者:井上治 URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev 変更履歴内容------------------------------------------------------------------------>
'05/11/14(1.00)新規作成
'12/03/26(1.01)初回修正
'20/03/02(1.10)*.xlsm化、他
'***************************************************************************************************
Option Explicit
'***************************************************************************************************
' ■■■ ワークシート側からの呼び出し処理 ■■■
'***************************************************************************************************
'* 処理名 :非ロックセルの確認
'* 機能 :非ロックセルの確認
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数 :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2005年11月14日
'* 作成者 :井上 治
'* 更新日 :2020年03月02日
'* 更新者 :井上 治
'* 機能説明:在籍名簿人数と「机」の数が一致しているかの確認
'* 注意事項:
'***************************************************************************************************
Sub 非ロックセルの確認()
'-----------------------------------------------------------------------------------------------
Dim objSh1 As Worksheet ' 座席表シート
Dim objSh2 As Worksheet ' 在籍名簿シート
Dim objR As Range ' セル
Dim cntKensu1 As Long ' 座席表の非ロックセル数
Dim cntKensu2 As Long ' 在籍名簿の人数
Dim strRange As String ' セルアドレス
Set objSh1 = ThisWorkbook.Worksheets(g_cnsSH1)
Set objSh2 = ThisWorkbook.Worksheets(g_cnsSH2)
'---------------------------------------------------------------------------
' 在籍名簿シート
With objSh2
' フィルタ解除
If .FilterMode Then .ShowAllData
' 登録人数の取得
cntKensu2 = .Range("$A$" & .Rows.Count).End(xlUp).Row - g_cnsCntMidashi
End With
' 座席表シートの使用領域をループ
For Each objR In objSh1.UsedRange
' 非ロックセルを対象とする
If Not objR.Locked Then
cntKensu1 = cntKensu1 + 1
' セルアドレスを追記
If strRange <> "" Then strRange = strRange & ","
strRange = strRange & objR.Address
End If
Next objR
' 座席表シートを表示
If ActiveSheet.Name <> g_cnsSH1 Then objSh1.Activate
objSh1.Range(strRange).Select
'---------------------------------------------------------------------------
If cntKensu1 = cntKensu2 Then
MsgBox """机""の数と在籍人数は合っています。", vbInformation
Else
MsgBox """机""の数と在籍人数が合っていません。" & vbCr & _
"""机""の数=" & cntKensu1 & vbCr & _
"在籍人数=" & cntKensu2, vbExclamation
End If
objSh1.Range("$A$1").Select
End Sub
'----------------------------------------<< End of Source >>----------------------------------------