- ベストアンサー
Excel2003(VBA)でタイプ別表を自動発生させる方法
- Excel2003(VBA)を使用して、入力情報に基づいてタイプ別の表を自動生成する方法を解説します。
- 入力情報は3列で構成され、A列には番号、B列には名前、C列にはタイプが記入されています。
- この情報を元に、出力結果の表を生成し、タイプに該当する箇所に○を付けることができます。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
[番号]は[名前]に対する一意なID、ということなのだとして。 Option Explicit ' ' 参照設定: Microsoft Scripting Runtime ' ' 参照設定した場合は【a/2択】に代えて【b/2択】をイキ ' ' シート名、セル範囲の指定は、適切に。 Sub Re8111840() Const タイプ = "SA1,SA2,SB1,SB2,SC1,SC2,SC3" Dim mtxS() ' 元データ 二次元配列 Dim mtxP() ' 出力用二次元配列 Dim arrT() As String ' タイプ配列 Dim oDictType As Object ' 【a/2択】 ' Dim oDictType As Scripting.Dictionary ' 【b/2択】 Dim oDictID As Object ' 【a/2択】 ' Dim oDictID As Scripting.Dictionary ' 【b/2択】 Dim tnR As Long ' レコード数 Dim tnF As Long ' 出力先フィールド数 Dim cnt As Long ' 出力先レコード数 Dim nID As Long ' 文字列を除いた番号 Dim i As Long ' ' タイプTable作成 arrT = Split(タイプ, ",") tnF = UBound(arrT) + 3 Set oDictType = CreateObject("Scripting.Dictionary") ' 【a/2択】 ' Set oDictType = New Scripting.Dictionary ' 【b/2択】 For i = 3 To tnF oDictType(arrT(i - 3)) = i Next i ' ' 元データを二次元配列で取得 With Sheets("Sheet1") mtxS() = .Range("A2:C" & .Cells(2, 1).End(xlDown).Row).Value End With tnR = UBound(mtxS) ' ' 出力用配列サイズを不足がないサイズで大き目に再定義 ReDim mtxP(1 To tnR, 1 To tnF) Set oDictID = CreateObject("Scripting.Dictionary") ' 【a/2択】 ' Set oDictID = New Scripting.Dictionary ' 【b/2択】 ' ' oDictIDはIDに応じた出力用配列(mtxP)の行位置(Y座標)を ' ' oDictTypeは元データ3列目[タイプ]に応じた出力用配列(mtxP)の列位置(X座標)を For i = 1 To tnR nID = PickUpNum(mtxS(i, 1)) If nID Then If oDictID.Exists(nID) Then mtxP(oDictID(nID), oDictType(mtxS(i, 3))) = "○" Else cnt = cnt + 1 oDictID(nID) = cnt mtxP(cnt, 1) = nID mtxP(cnt, 2) = mtxS(i, 2) mtxP(cnt, oDictType(mtxS(i, 3))) = "○" End If End If Next i Set oDictType = Nothing: Set oDictID = Nothing Erase mtxS() With Sheets("Sheet2") .Cells(3, 1).Resize(cnt, tnF).Value = mtxP() .Range("A2:B2").Value = Array("番号", "名前") .Cells(1, 3).Resize(, tnF - 2).Value = arrT End With Erase arrT, mtxP() End Sub Private Function PickUpNum(ByVal S As String) As Long Dim i As Long For i = 1 To Len(S) If IsNumeric(Mid$(S, i)) Then PickUpNum = Val(Mid$(S, i)) Exit For End If Next i End Function
その他の回答 (1)
- tom04
- ベストアンサー率49% (2537/5117)
こんにちは! 一例です。 Sheet1のデータをSheet2に表示するようにしてみました。 Sheet2の1行目の項目、2行目の「番号」・「名前」は入力済みだとします。 標準モジュールに↓のコードをコピー&ペーストしてマクロを実行してみてください。 Sub Sample1() Dim i As Long, j As Long, k As Long, c As Range, wS1 As Worksheet, wS2 As Worksheet, myFlg As Boolean Set wS1 = Worksheets("Sheet1") Set wS2 = Worksheets("Sheet2") Application.ScreenUpdating = False i = wS2.Cells(Rows.Count, 1).End(xlUp).Row If i > 2 Then Range(wS2.Cells(3, "A"), wS2.Cells(i, "I")).ClearContents End If For i = 2 To wS1.Cells(Rows.Count, 1).End(xlUp).Row myFlg = False For k = 1 To Len(wS1.Cells(i, 1)) If Mid(wS1.Cells(i, 1), k, 1) Like "[a-z A-Z]" Then myFlg = True Exit For End If Next k If myFlg = False Then Set c = wS2.Range("A:A").Find(what:=wS1.Cells(i, 1), LookIn:=xlValues, lookat:=xlWhole) If c Is Nothing Then wS1.Cells(i, 1).Resize(1, 2).Copy wS2.Cells(Rows.Count, 1).End(xlUp).Offset(1) End If End If Next i For k = 3 To wS2.Cells(Rows.Count, 1).End(xlUp).Row For i = 2 To wS1.Cells(Rows.Count, 1).End(xlUp).Row If InStr(wS1.Cells(i, 1), wS2.Cells(k, 1)) > 0 Then j = WorksheetFunction.Match(wS1.Cells(i, 3), wS2.Range("1:1"), False) wS2.Cells(k, j) = "○" End If Next i Next k Application.ScreenUpdating = True End Sub ※ Sheet1のC列データは同番号が含まれている人に重複はない!とします。 こんなんではどうでしょうか?m(_ _)m
お礼
ありがとうございます。 ご丁寧な回答感謝します。