URLをクリップポードにコピーした状態からワンクリックでショートカットを作成

1 目的

シェアポイントのアドレスはコピーすると長過ぎてWindowsのショートカットに収まらず途中で切れてしまう。そこで、バッチファイル からps1ファイルを呼び出して手当てする。

2 コード

batファイル

Run_make_shortcut.bat

powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0make_shortcut.ps1"

ps1ファイル

make_shortcut.ps1

 <#
    URLショートカット作成ツール

    やっていること:
    1. ショートカットの名前をユーザーに入力させる
    2. クリップボードにコピーされているURL(SharePointのリンクなど)を取得する
    3. そのURLをEdgeで開くだけの .bat ファイルを作る
    4. 同名ファイルによる上書きを防ぐため、ファイル名の末尾に作成日時を付加する
    5. 出来上がった .bat ファイルは、この .ps1 ファイルと同じフォルダに保存される

    ファイル名: make_shortcut.ps1
    起動用ランチャー: Run_make_shortcut.bat
      (中身: powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0make_shortcut.ps1")

    使い方:
    - このスクリプトを実行する前に、対象URLをコピー(Ctrl+C)しておく
    - 実行するとショートカット名の入力を求められるので、任意の名前を入力する
    - 完了すると .bat ファイルが作成され、ダブルクリックでそのURLをEdgeで開けるようになる
#>

# ユーザーにショートカット名を入力させ、$name に格納する
$name = Read-Host "ショートカット名"

# ファイル名として使えない禁則文字(\ / : * ? " < > |)を
# アンダースコア "_" に置き換えた安全な名前を作る
$safeName = $name -replace '[\\/:*?"<>|]', '_'

# クリップボードにコピーされている文字列(SharePointのURLなど)を取得
$clip = Get-Clipboard

# 生成する.batファイルの中身を文字列として組み立てる
# `r`n は改行(CRLF)を意味する特殊文字
# `"`" は「空のダブルクォート " " 」を出力するためのエスケープ表現
# 最終的にできる中身のイメージ:
#   @echo off
#   start "" msedge "https://sharepoint.example.com/..."
$content = "@echo off`r`nstart `"`" msedge `"$clip`""

# 同名ファイルによる上書きを防ぐため、現在日時を "yyyyMMdd-HHmmss" 形式で取得し、
# ファイル名の末尾に付加する(例: 会議URL_20260717-143025.bat)
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"

# 保存先のフルパスを作る
# $PSScriptRoot は「このps1ファイルが置かれているフォルダ」を指す
# そこに $safeName + "_" + タイムスタンプ + ".bat" というファイル名を連結する
$path = Join-Path $PSScriptRoot "$safeName`_$timestamp.bat"

# 組み立てた中身($content)を、上で決めたパス($path)に
# UTF-8エンコーディングで書き出す(=新しいbatファイルが作られる)
Set-Content -Path $path -Value $content -Encoding UTF8

# 完了メッセージとして、作成したファイルのパスを画面に表示する
Write-Host "作成しました: $path"

3 claude

 

複数グループから提出されたものに、通し番号を付与して50件ずつ束を作成する。

1目的

 

2コード

 

Option Explicit

'============================================================
' モジュール名
'   mod提出物採番して外注束作成
'
' Version
'   1.1
'
'【目的】
' 読取シートへ入力した会社ごとの提出件数を、
' 50件単位の外注束へ展開して出力シートへ出力する。
'
'【設計方針】
' ・シートレイアウトはExcel側で管理する。
' ・見出し・書式・列幅はVBAで変更しない。
' ・VBAはデータのみ出力する。
' ・読取順に処理する。
' ・変数は初めて意味を持つブロックで宣言する。
' ・コメントは処理の区切りと、コードだけでは伝わらない
'   設計意図のみ記述する。
'============================================================

Private Enum cNoWs読取
    会社名 = 1
    件数 = 2
End Enum

Private Enum cNoWs出力
    ID = 1
    会社名 = 2
    件数 = 3
    束番号 = 4
    開始番号 = 5
    終了番号 = 6
End Enum

Sub 出力作成()

    '======== 定数 ========

    Const 最大束件数 As Long = 50

    Const 読取シート名 As String = "入力"
    Const 出力シート名 As String = "出力"

    Const 読取開始行 As Long = 2
    Const 出力開始行 As Long = 2

    '======== シート取得 ========

    Dim ws読取 As Worksheet
    Dim ws出力 As Worksheet

    Set ws読取 = Worksheets(読取シート名)
    Set ws出力 = Worksheets(出力シート名)

    '======== 出力シート初期化 ========

    ws出力.Rows(出力開始行 & ":" & ws出力.Rows.Count).ClearContents

    '======== 採番初期化 ========

    Dim lng現在束番号 As Long
    Dim lng現在束残件数 As Long
    Dim lng次開始番号 As Long
    Dim lng次行ID As Long
    Dim rNo出力行 As Long

    lng現在束番号 = 1
    lng現在束残件数 = 最大束件数
    lng次開始番号 = 1
    lng次行ID = 1
    rNo出力行 = 出力開始行

    '======== 読取データを順番に処理 ========

    Dim rNo読取最終行 As Long
    Dim rNo読取行 As Long

    rNo読取最終行 = ws読取.Cells(ws読取.Rows.Count, cNoWs読取.会社名).End(xlUp).Row

    For rNo読取行 = 読取開始行 To rNo読取最終行

        Dim str会社名 As String
        Dim lng会社残件数 As Long

        str会社名 = ws読取.Cells(rNo読取行, cNoWs読取.会社名).Value
        lng会社残件数 = ws読取.Cells(rNo読取行, cNoWs読取.件数).Value

        '会社より50件単位を優先して束を構成する
        Do While lng会社残件数 > 0

            '======== 今回出力件数を決定 ========

            Dim lng今回出力件数 As Long

            If lng会社残件数 <= lng現在束残件数 Then
                lng今回出力件数 = lng会社残件数
            Else
                lng今回出力件数 = lng現在束残件数
            End If

            '======== 開始番号・終了番号を決定 ========

            Dim lng終了番号 As Long

            lng終了番号 = lng次開始番号 + lng今回出力件数 - 1

            '======== 出力 ========

            ws出力.Cells(rNo出力行, cNoWs出力.ID).Value = lng次行ID
            ws出力.Cells(rNo出力行, cNoWs出力.会社名).Value = str会社名
            ws出力.Cells(rNo出力行, cNoWs出力.件数).Value = lng今回出力件数
            ws出力.Cells(rNo出力行, cNoWs出力.束番号).Value = lng現在束番号

            ws出力.Cells(rNo出力行, cNoWs出力.開始番号).Value = lng次開始番号
            ws出力.Cells(rNo出力行, cNoWs出力.終了番号).Value = lng終了番号

            '======== 状態更新 ========

            lng会社残件数 = lng会社残件数 - lng今回出力件数
            lng現在束残件数 = lng現在束残件数 - lng今回出力件数

            lng次開始番号 = lng終了番号 + 1

            lng次行ID = lng次行ID + 1
            rNo出力行 = rNo出力行 + 1

            If lng現在束残件数 = 0 Then
                lng現在束番号 = lng現在束番号 + 1
                lng現在束残件数 = 最大束件数
            End If

        Loop

    Next rNo読取行

    '======== 完了 ========

    MsgBox "出力が完了しました。"

End Sub

以下claude版

 

Option Explicit

'============================================================
' モジュール名
'   mod提出物採番して外注束作成
'
' Version
'   2.9
'
'【目的】
' 読取シートへ入力した会社ごとの提出件数を、
' 50件単位の外注束へ展開して出力シートへ出力する。
'
'【設計方針】
' ・シートレイアウトはExcel側で管理する。
' ・見出し・書式・列幅はVBAで変更しない。
' ・VBAはデータのみ出力する。
' ・読取順に処理する。
' ・変数は初めて意味を持つブロックで宣言する。
' ・役割(書込み先/読取り元)が異なる行番号は、たとえ同じシートを
'   指していても変数を使い回さず、別の変数名として書き分ける。
' ・行番号変数は「RNo_シート名_役割」の形式で命名し、
'   どのシートのどの用途の行番号かを本文だけで判別できるようにする。
' ・データ値の変数も同様に「型_ws_シート名_列名(用途)」の形式で
'   命名し、どのシートのどの列に対応する値かを本文だけで
'   判別できるようにする。
'
'【コメント方針】
' ・コメントは処理の区切り(ステップの節目)や、コードだけでは
'   伝わらない設計意図・判断理由を記述する。
' ・特に、複数の判定や処理が連続していて、それぞれが何をしているか
'   一目で分からない箇所(連続するIf文、If-Elseの分岐など)や、
'   ループ・変数宣言・分岐の直前など、コードだけでは目的が
'   伝わりにくい箇所には、一言添える。
' ・変数名や条件式自体が文として読める箇所は、コメントがなくても
'   読み下せることが多いが、他の判断基準を優先してよい。
'
'【出力の粒度について】
' ・「束」は読取順の通し番号に対して50件ごとに機械的に区切られる
'   (会社の境界は一切考慮しない)。
' ・出力シートの1行は「束まるごと」ではなく「束×会社」の単位になる。
'   1つの束に複数社が含まれる場合や、1社が複数束にまたがる場合は、
'   会社が変わる箇所・束が変わる箇所のどちらでも行を分ける。
'
'【採番方式について】
' ・通し番号・束番号・束内番号は、いずれも割り算や逆算によらず、
'   作業シートへの展開と同時にカウンタを1件ずつ加算(必要に応じて
'   リセット)することで採番する。
' ・開始番号・終了番号は、束内番号ではなく全体を通した通し番号を
'   使う。これにより、あるデータが全体の何件目から何件目に
'   あたるかを、束をまたいでも一意に追跡できる。
' ・束枝番は「塊(会社×束の塊)が変わったかどうか」という、
'   塊が確定して初めて定義できる情報である。そのため作業シート
'   (1件単位)の段階では採番せず、出力シート(塊単位)が
'   完成した後にステップ3として改めて上から見て採番する。
'   判定は単純で、出力シートを上から見て、束番号が1行上と同じ
'   なら束枝番を1加算、違えば1にリセットする。
'============================================================

'読取シートの列番号
Private Enum CNoWs読取
    会社名 = 1
    件数 = 2
End Enum

'作業シートの列番号
Private Enum CNoWs作業
    通し番号 = 1
    会社名 = 2
    束番号 = 3
    束内番号 = 4
End Enum

'出力シートの列番号
Private Enum CNoWs出力
    ID = 1
    会社名 = 2
    件数 = 3
    束番号 = 4
    束枝番 = 5
    開始番号 = 6
    終了番号 = 7
End Enum

Sub 出力作成()

    '======== 定数 ========

    '読取シート
    Const str読取シート名 As String = "読取"
    Const RNo_ws読取_開始行 As Long = 2

    '作業シート
    Const str作業シート名 As String = "作業"
    Const RNo_ws作業_開始行 As Long = 2

    '出力シート
    Const str出力シート名 As String = "出力"
    Const RNo_ws出力_開始行 As Long = 2

    Const lng最大束件数 As Long = 50

    '======== シート取得 ========

    Dim ws読取 As Worksheet
    Dim ws作業 As Worksheet
    Dim ws出力 As Worksheet

    Set ws読取 = Worksheets(str読取シート名)
    Set ws作業 = Worksheets(str作業シート名)
    Set ws出力 = Worksheets(str出力シート名)

    ws作業.Rows(RNo_ws作業_開始行 & ":" & ws作業.Rows.Count).ClearContents
    ws出力.Rows(RNo_ws出力_開始行 & ":" & ws出力.Rows.Count).ClearContents

    '======== ステップ1:会社名を件数分だけ作業シートへ展開し、束番号・束内番号も同時に採番 ========
    ' 1行書き込むたびに、通し番号・束内番号を1ずつ進める。
    ' 束内番号が50を超えたら、束番号を1つ進めて束内番号を1に戻す。

    Dim RNo_ws読取_最終行 As Long
    RNo_ws読取_最終行 = ws読取.Cells(ws読取.Rows.Count, CNoWs読取.会社名).End(xlUp).Row

    Dim RNo_ws作業_書込行 As Long
    RNo_ws作業_書込行 = RNo_ws作業_開始行

    '通し番号・束番号・束内番号のカウンタを初期化する
    Dim lng_ws作業_通し番号 As Long
    lng_ws作業_通し番号 = 0

    Dim lng_ws作業_束番号 As Long
    Dim lng_ws作業_束内番号 As Long
    lng_ws作業_束番号 = 1
    lng_ws作業_束内番号 = 0

    '読取シートを1行ずつ、会社の登場順に処理する
    Dim RNo_ws読取_読取行 As Long
    For RNo_ws読取_読取行 = RNo_ws読取_開始行 To RNo_ws読取_最終行

        Dim str_ws読取_会社名 As String
        Dim lng_ws読取_件数 As Long
        str_ws読取_会社名 = ws読取.Cells(RNo_ws読取_読取行, CNoWs読取.会社名).Value
        lng_ws読取_件数 = ws読取.Cells(RNo_ws読取_読取行, CNoWs読取.件数).Value

        '1社分の件数だけ、作業シートへ1件ずつ展開する
        Dim i As Long
        For i = 1 To lng_ws読取_件数

            lng_ws作業_通し番号 = lng_ws作業_通し番号 + 1

            lng_ws作業_束内番号 = lng_ws作業_束内番号 + 1
            If lng_ws作業_束内番号 > lng最大束件数 Then
                lng_ws作業_束番号 = lng_ws作業_束番号 + 1
                lng_ws作業_束内番号 = 1
            End If

            ws作業.Cells(RNo_ws作業_書込行, CNoWs作業.通し番号).Value = lng_ws作業_通し番号
            ws作業.Cells(RNo_ws作業_書込行, CNoWs作業.会社名).Value = str_ws読取_会社名
            ws作業.Cells(RNo_ws作業_書込行, CNoWs作業.束番号).Value = lng_ws作業_束番号
            ws作業.Cells(RNo_ws作業_書込行, CNoWs作業.束内番号).Value = lng_ws作業_束内番号

            RNo_ws作業_書込行 = RNo_ws作業_書込行 + 1

        Next i

    Next RNo_ws読取_読取行

    Dim lng総件数 As Long
    lng総件数 = lng_ws作業_通し番号

    '======== ステップ2:作業シートを上から転記し、会社名か束番号が変わったら出力行を改める ========
    ' 出力1行=「束×会社」の単位。会社の境界・束の境界のどちらでも区切る。
    ' 束枝番はこの時点ではまだ振らない(ステップ3でまとめて振る)。

    '出力行番号・出力IDのカウンタを初期化する
    Dim RNo_ws出力_書込行 As Long: RNo_ws出力_書込行 = RNo_ws出力_開始行
    Dim lng_ws出力_ID As Long: lng_ws出力_ID = 1

    '「同じ会社」かつ「同じ束番号」が連続している塊の先頭行。
    '塊の終わりは読み進めれば都度わかるが、始まりは
    '前の区切りの次まで遡らないとわからないため保持しておく。
    Dim RNo_ws作業_区間開始行 As Long: RNo_ws作業_区間開始行 = RNo_ws作業_開始行

    Dim RNo_ws作業_読取行 As Long
    For RNo_ws作業_読取行 = RNo_ws作業_開始行 To RNo_ws作業_開始行 + lng総件数 - 1

        Dim is改行予定 As Boolean
        is改行予定 = False

        '最終行に達したら、無条件で塊の区切りとする
        If RNo_ws作業_読取行 = RNo_ws作業_開始行 + lng総件数 - 1 Then is改行予定 = True
        '次の行で会社が変わるなら、そこで塊を区切る
        If ws作業.Cells(RNo_ws作業_読取行 + 1, CNoWs作業.会社名).Value <> ws作業.Cells(RNo_ws作業_区間開始行, CNoWs作業.会社名).Value Then is改行予定 = True
        '次の行で束番号が変わるなら、そこでも塊を区切る
        If ws作業.Cells(RNo_ws作業_読取行 + 1, CNoWs作業.束番号).Value <> ws作業.Cells(RNo_ws作業_区間開始行, CNoWs作業.束番号).Value Then is改行予定 = True

        If is改行予定 Then

            ws出力.Cells(RNo_ws出力_書込行, CNoWs出力.ID).Value = lng_ws出力_ID
            ws出力.Cells(RNo_ws出力_書込行, CNoWs出力.会社名).Value = ws作業.Cells(RNo_ws作業_区間開始行, CNoWs作業.会社名).Value
            ws出力.Cells(RNo_ws出力_書込行, CNoWs出力.件数).Value = RNo_ws作業_読取行 - RNo_ws作業_区間開始行 + 1
            ws出力.Cells(RNo_ws出力_書込行, CNoWs出力.束番号).Value = ws作業.Cells(RNo_ws作業_区間開始行, CNoWs作業.束番号).Value
            ws出力.Cells(RNo_ws出力_書込行, CNoWs出力.開始番号).Value = ws作業.Cells(RNo_ws作業_区間開始行, CNoWs作業.通し番号).Value
            ws出力.Cells(RNo_ws出力_書込行, CNoWs出力.終了番号).Value = ws作業.Cells(RNo_ws作業_読取行, CNoWs作業.通し番号).Value

            lng_ws出力_ID = lng_ws出力_ID + 1
            RNo_ws出力_書込行 = RNo_ws出力_書込行 + 1
            RNo_ws作業_区間開始行 = RNo_ws作業_読取行 + 1

        End If

    Next RNo_ws作業_読取行

    '======== ステップ3:出力シートを上から見て、束番号が1行上と同じなら束枝番を加算 ========
    ' 出力シートは既に「束×会社」の塊単位で1行にまとまっているため、
    ' ここでは束番号の変化を見るだけで枝番が決まる。
    ' 直前の束番号の初期値は0(実在しない束番号)にしておくことで、
    ' 1行目は必ず「変わった」と判定され、束枝番が1から始まる。

    Dim RNo_ws出力_最終行 As Long
    RNo_ws出力_最終行 = RNo_ws出力_書込行 - 1

    '束枝番・直前の束番号のカウンタを初期化する
    Dim lng_ws出力_束枝番 As Long
    lng_ws出力_束枝番 = 0

    Dim lng_ws出力_直前の束番号 As Long
    lng_ws出力_直前の束番号 = 0

    Dim RNo_ws出力_採番行 As Long
    For RNo_ws出力_採番行 = RNo_ws出力_開始行 To RNo_ws出力_最終行

        Dim lng_ws出力_現在の束番号 As Long
        lng_ws出力_現在の束番号 = ws出力.Cells(RNo_ws出力_採番行, CNoWs出力.束番号).Value

        If lng_ws出力_現在の束番号 = lng_ws出力_直前の束番号 Then
            '同じ束の中がまだ続いているので、枝番を1つ進める
            lng_ws出力_束枝番 = lng_ws出力_束枝番 + 1
        Else
            '新しい束に入ったので、枝番を1からリセットする
            lng_ws出力_束枝番 = 1
            lng_ws出力_直前の束番号 = lng_ws出力_現在の束番号
        End If

        ws出力.Cells(RNo_ws出力_採番行, CNoWs出力.束枝番).Value = lng_ws出力_束枝番

    Next RNo_ws出力_採番行

    '======== 完了 ========

    MsgBox "出力が完了しました。"

End Sub

3参考

 

chatGPT

 

エクセルを閉じるとき上書き保存してOutlookでメール送信マクロ

1 目的

エクセルを更新して閉じるときに、"送信先リスト"というシートのセル範囲C2:C11に書かれたメールアドレス宛にファイルを更新した旨のメールを自動送信する。

2 コード

注)ブックのイベントなので記載場所はThisworkbook

' Workbook - 改善版
Option Explicit

' ファイルを開いた時に入力シートを表示する
Private Sub Workbook_Open()
    On Error Resume Next
    Worksheets("入力シート").Activate
End Sub

' ファイルを閉じるときにメールを送信する
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    On Error GoTo ErrorHandler
    
    ' 定数定義
    Const WS_送信先リスト As String = "送信先リスト"
    Const COL_EMAIL As Integer = 3
    Const LNG_XLSM拡張子文字数 As Integer = 5 ' ".xlsm"の文字数
    
    Dim m As String
    m = ""
    m = m & "処理担当Gにメールを送信しますか?" & vbCrLf
    m = m & "「はい」なら上書き保存し、メール送信します。" & vbCrLf
    m = m & "「いいえ」なら上書き保存とメール送信を中止します。保存は自分で行なってください。"
    
    ' 早期リターン:「いいえ」を選んだときは終了する
    If MsgBox(m, vbYesNo) = vbNo Then
        MsgBox "保存と送信を中止しました。"
        Exit Sub
    End If
    
    ' ====これ以降はメッセージボックスで「はい」を選んだときの処理====
    
    ' 上書き保存
    ThisWorkbook.Save
    
    ' Outlookオブジェクト作成
    Dim myOL As Object: Set myOL = CreateObject("Outlook.Application")
    Dim myMail As Object: Set myMail = myOL.CreateItem(0)
    
    ' 送信先リストから全てのセルのメールアドレスを指定する
    ' Outlookは末尾や連続したセミコロンを無視するため、整形は不要
    With Worksheets(WS_送信先リスト)
        myMail.To = .Cells(2, COL_EMAIL) & ";" & _
                    .Cells(3, COL_EMAIL) & ";" & _
                    .Cells(4, COL_EMAIL) & ";" & _
                    .Cells(5, COL_EMAIL) & ";" & _
                    .Cells(6, COL_EMAIL) & ";" & _
                    .Cells(7, COL_EMAIL) & ";" & _
                    .Cells(8, COL_EMAIL) & ";" & _
                    .Cells(9, COL_EMAIL) & ";" & _
                    .Cells(10, COL_EMAIL) & ";" & _
                    .Cells(11, COL_EMAIL)
    End With
    
    ' 件名設定
    myMail.Subject = "【自動送信】" & Left(ThisWorkbook.Name, Len(ThisWorkbook.Name) - LNG_XLSM拡張子文字数) & "更新のお知らせ"
    
    ' メール本文作成
    Dim strBody As String
    strBody = ""
    strBody = strBody & "このメールは、リストを更新した際に自動で送信されます。<br>"
    strBody = strBody & "ファイル名:" & ThisWorkbook.Name & " 」 は<br>"
strBody = strBody & "<a href='file://" & ThisWorkbook.Path & "'>" & ThisWorkbook.Path & "</a><br>"
    strBody = strBody & "<br>"
  strBody = strBody & "に保存されています。" ' HTMLメール設定と送信 myMail.HTMLBody = strBody myMail.Send ' オブジェクトの解放(COMオブジェクトのみ) Set myMail = Nothing Set myOL = Nothing Exit Sub ErrorHandler: MsgBox "メール送信時にエラーが発生しました: " & Err.Description Set myMail = Nothing Set myOL = Nothing End Sub

 

3 参考

既存コードをレビューした。

 

複数シートのラベルデータからDB形式へ変換して集約。

1 目的

複数行使って1レコードを表現するラベル型のなんちゃってDBから1レコード1行のDB形式へ変換するコードの、複数シート集約版。ラベルの形は前シートで完全に同じことが前提。

2コード

 

'==============================================================================
' ラベルデータからDBへ変換する(全シート集約版)
'==============================================================================
' 【機能】
'   ワークブック内の全シート(転記先DB以外)のラベル形式データを読み取り、
'   1つのデータベース形式シートに集約する
'
' 【参照の有無】
'   参照なし(標準ライブラリのみ使用)
'
' 【変数の省略記号】
'   Src = Source(読み取り元)
'   Dst = Destination(転記先)
'   ws  = Worksheet
'   col = Column(列)
'   row = Row(行)
'   i   = Index(ループ変数の接頭辞)
'
' 【想定シート構成】
'   - 複数のラベルシート: ラベル形式でデータが配置されたシート群
'   - 転記先DB: 変換後のデータベース形式データを出力するシート
'
' 【想定データレイアウト】
'   各ラベルは指定された幅×高さの矩形領域に配置
'   ラベル内の各項目は相対位置で定義(左上角からのオフセット)
'
' 【使い方】
'   1. 転記先DBシートを作成
'   2. マクロを実行(全シートを自動処理)
'   ※設定値・フィールド定義は「単一シートのラベルを変換」関数内で定義
'==============================================================================

'==============================================================================
' メイン処理:全シートのラベルデータを集約
'==============================================================================
Sub 全シートのラベルデータを集約する()
    Dim wsDst As Worksheet
    Set wsDst = ThisWorkbook.Sheets("転記先DB")
    
    '=== 出力先をクリア ===
    wsDst.Cells.Clear
    
    '=== 見出しを書き出し(フィールド定義は単一シート変換関数内を参照) ===
    wsDst.Cells(1, 1).Value = "氏名"
    wsDst.Cells(1, 2).Value = "生年月日"
    wsDst.Cells(1, 3).Value = "性別"
    wsDst.Cells(1, 4).Value = "住所"
    wsDst.Cells(1, 5).Value = "電話番号"  
    wsDst.Cells(1, 6).Value = "メール"
    
    '=== 各シートを処理 ===
    Dim wsSrc As Worksheet
    For Each wsSrc In ThisWorkbook.Worksheets
        If wsSrc.Name <> wsDst.Name Then
            Call 単一シートのラベルを変換(wsSrc, wsDst)
        End If
    Next
    
    MsgBox "全シート変換完了"
End Sub

'==============================================================================
' 単一シートのラベルデータを変換
'==============================================================================
Sub 単一シートのラベルを変換(wsSrc As Worksheet, wsDst As Worksheet)
    '=== 設定値 ===
    Dim colラベル開始列 As Long: colラベル開始列 = 1          ' 開始列
    Dim rowラベル開始行 As Long: rowラベル開始行 = 2          ' 開始行
    Dim labelWidth As Long: labelWidth = 3        ' ラベル1個の幅(列数)
    Dim labelHeight As Long: labelHeight = 5      ' ラベル1個の高さ(行数)
    Dim colラベル最終列 As String: colラベル最終列 = "I"      ' ラベルが使用する最終列記号

    '=== キーに対する相対位置(行, 列)===
    ' ラベルの左上角(キー位置)からの相対位置で定義
    Dim dicラベル内のoffset As Object
    Set dicラベル内のoffset = CreateObject("Scripting.Dictionary")
    dicラベル内のoffset.Add "氏名", Array(0, 0)      ' キー位置そのもの
    dicラベル内のoffset.Add "生年月日", Array(0, 1)  ' キー位置から右に1列
    dicラベル内のoffset.Add "性別", Array(0, 2)      ' キー位置から右に2列
    dicラベル内のoffset.Add "住所", Array(1, 0)      ' キー位置から下に1行
    dicラベル内のoffset.Add "電話番号", Array(1, 1)  ' キー位置から下に1行、右に1列
    dicラベル内のoffset.Add "メール", Array(1, 2)    ' キー位置から下に1行、右に2列

    Dim lastRow As Long: lastRow = wsSrc.UsedRange.Rows.Count
    Dim lastCol As Long: lastCol = wsSrc.Range(colラベル最終列 & "1").Column
    
    ' 転記先の次の空行を取得
    Dim iRowDst As Long: iRowDst = wsDst.Cells(wsDst.Rows.Count, 1).End(xlUp).Row + 1

    '=== 縦方向のラベルを処理 ===
    Dim iRowSrc As Long: iRowSrc = rowラベル開始行
    Do While iRowSrc <= lastRow
        
        '=== 横方向のラベルを処理 ===
        Dim iColSrc As Long: iColSrc = colラベル開始列
        Do While iColSrc <= lastCol
            
            Dim pos As Variant: pos = dicラベル内のoffset("氏名")
            Dim is氏名セルに値がある As Boolean
            is氏名セルに値がある = (Trim(CStr(wsSrc.Cells(iRowSrc, iColSrc).Offset(pos(0), pos(1)).Value)) <> "")
            
            ' 氏名が空でない場合のみ処理
            If is氏名セルに値がある Then
                Dim iColDst As Long: iColDst = 1
                Dim key As Variant
                For Each key In dicラベル内のoffset.Keys
                    pos = dicラベル内のoffset(key)
                    wsDst.Cells(iRowDst, iColDst).Value = wsSrc.Cells(iRowSrc, iColSrc).Offset(pos(0), pos(1)).Value
                    iColDst = iColDst + 1
                Next
                iRowDst = iRowDst + 1
            End If
            
            iColSrc = iColSrc + labelWidth ' 次のラベル列(横方向)
        Loop
        
        iRowSrc = iRowSrc + labelHeight ' 次のラベル行(縦方向)
    Loop
End Sub

3参考

claude

ラベル型配置や複数行を使ったナンチャッテDBから1行1レコードのDBを再構成するマクロ

1  目的

1レコードが3行とか5行とか使って書かれているなんちゃってDBというのが実務ではよくある。マクロ処理しようとするとoffsetを使ったりして複雑になり手間がかかる。

そこで、1レコードが複数行を使って書かれた中途半端なリストや、1レコードが複数行かつ複数列で、さらに列方向にも行方向にも繰り返されている印刷ラベルのようななんちゃってDBから、1行1レコードの使いやすいDB形式を再構成するマクロ。

 

2 コード

 

'====================================================================
' ラベルデータからDBへ変換する
'====================================================================
' 【機能】
'   ラベル形式で配置されたデータを読み取り、データベース形式(行列形式)に変換する
'
' 【参照の有無】
'   参照なし(標準ライブラリのみ使用)
'
' 【変数の省略記号】
'   Src = Source(読み取り元)
'   Dst = Destination(転記先)
'   ws  = Worksheet
'   col = Column(列)
'   row = Row(行)
'   i   = Index(ループ変数の接頭辞)
'
' 【想定シート構成】
'   - 読取元ラベル: ラベル形式でデータが配置されたシート
'   - 転記先DB: 変換後のデータベース形式データを出力するシート
'
' 【想定データレイアウト】
'   各ラベルは指定された幅×高さの矩形領域に配置
'   ラベル内の各項目は相対位置で定義(左上角からのオフセット)
'
' 【使い方】
'   1. 設定値セクションで開始位置・サイズ・範囲を調整
'   2. dicラベル内のoffsetで各項目の相対位置を定義
'   3. マクロを実行
'====================================================================
Sub ラベルデータからDBへ変換する()
    Dim wsSrc As Worksheet, wsDst As Worksheet

    Set wsSrc = ThisWorkbook.Sheets("読取元ラベル") ' 元のラベルデータ
    Set wsDst = ThisWorkbook.Sheets("転記先DB") ' 出力先

    '=== 設定値 ===
    Dim colラベル開始列 As Long: colラベル開始列 = 1          ' 開始列
    Dim rowラベル開始行 As Long: rowラベル開始行 = 2          ' 開始行
    Dim labelWidth As Long: labelWidth = 3        ' ラベル1個の幅(列数)
    Dim labelHeight As Long: labelHeight = 5      ' ラベル1個の高さ(行数)
    Dim colラベル最終列 As String: colラベル最終列 = "I"      ' ラベルが使用する最終列記号

    '=== キーに対する相対位置(行, 列)===
    ' ラベルの左上角(キー位置)からの相対位置で定義
    Dim dicラベル内のoffset As Object
    Set dicラベル内のoffset = CreateObject("Scripting.Dictionary")
    dicラベル内のoffset.Add "氏名", Array(0, 0)      ' キー位置そのもの
    dicラベル内のoffset.Add "生年月日", Array(0, 1)  ' キー位置から右に1列
    dicラベル内のoffset.Add "性別", Array(0, 2)      ' キー位置から右に2列
    dicラベル内のoffset.Add "住所", Array(1, 0)      ' キー位置から下に1行
    dicラベル内のoffset.Add "電話番号", Array(1, 1)  ' キー位置から下に1行、右に1列
    dicラベル内のoffset.Add "メール", Array(1, 2)    ' キー位置から下に1行、右に2列

    '=== 出力先をクリア ===
    wsDst.Cells.Clear

    '=== 見出しを書き出し ===
    Dim iColDst As Long: iColDst = 1
    Dim key As Variant
    For Each key In dicラベル内のoffset.Keys
        wsDst.Cells(1, iColDst).Value = key
        iColDst = iColDst + 1
    Next

    Dim iRowDst As Long: iRowDst = 2
    Dim lastRow As Long: lastRow = wsSrc.UsedRange.Rows.Count
    Dim lastCol As Long: lastCol = wsSrc.Range(colラベル最終列 & "1").Column

    '=== 縦方向のラベルを処理 ===
    Dim iRowSrc As Long: iRowSrc = rowラベル開始行
    Do While iRowSrc <= lastRow
        
        '=== 横方向のラベルを処理 ===
        Dim iColSrc As Long: iColSrc = colラベル開始列
        Do While iColSrc <= lastCol
            
            Dim pos As Variant: pos = dicラベル内のoffset("氏名")
            Dim is氏名セルに値がある As Boolean
            is氏名セルに値がある = (Trim(CStr(wsSrc.Cells(iRowSrc, iColSrc).Offset(pos(0), pos(1)).Value)) <> "")
            
            ' 氏名が空でない場合のみ処理
            If is氏名セルに値がある Then
                iColDst = 1
                For Each key In dicラベル内のoffset.Keys
                    pos = dicラベル内のoffset(key)
                    wsDst.Cells(iRowDst, iColDst).Value = wsSrc.Cells(iRowSrc, iColSrc).Offset(pos(0), pos(1)).Value
                    iColDst = iColDst + 1
                Next
                iRowDst = iRowDst + 1
            End If
            
            iColSrc = iColSrc + labelWidth ' 次のラベル列(横方向)
        Loop
        
        iRowSrc = iRowSrc + labelHeight ' 次のラベル行(縦方向)
    Loop
    
    MsgBox "変換完了: " & (iRowDst - 2) & "件のデータを処理しました。"
End Sub

 

 

3 claudeにあれこれ指示した。

 

 

 

 

ラベル型配置や複数行を使ったナンチャッテDBから1行1レコードのDBを再構成するマクロ

1  目的

1レコードが3行とか5行とか使って書かれているなんちゃってDBというのが実務ではよくある。マクロ処理しようとするとoffsetを使ったりして複雑になり手間がかかる。

そこで、1レコードが複数行を使って書かれた中途半端なリストや、1レコードが複数行かつ複数列で、さらに列方向にも行方向にも繰り返されている印刷ラベルのようななんちゃってDBから、1行1レコードの使いやすいDB形式を再構成するマクロ。

 

2 コード

 

'============================================================================== ' ラベルデータからDBへ変換する '============================================================================== ' 【機能】 ' ラベル形式で配置されたデータを読み取り、データベース形式(行列形式)に変換する ' ' 【参照の有無】 ' 参照なし(標準ライブラリのみ使用) ' ' 【変数の省略記号】 ' Src = Source(読み取り元) ' Dst = Destination(転記先) ' ws = Worksheet ' col = Column(列) ' row = Row(行) ' i = Index(ループ変数の接頭辞) ' ' 【想定シート構成】 ' - 読取元ラベル: ラベル形式でデータが配置されたシート ' - 転記先DB: 変換後のデータベース形式データを出力するシート ' ' 【想定データレイアウト】 ' 各ラベルは指定された幅×高さの矩形領域に配置 ' ラベル内の各項目は相対位置で定義(左上角からのオフセット) ' ' 【使い方】 ' 1. 設定値セクションで開始位置・サイズ・範囲を調整 ' 2. dicラベル内のoffsetで各項目の相対位置を定義 ' 3. マクロを実行 '============================================================================== Sub ラベルデータからDBへ変換する() Dim wsSrc As Worksheet, wsDst As Worksheet Set wsSrc = ThisWorkbook.Sheets("読取元ラベル") ' 元のラベルデータ Set wsDst = ThisWorkbook.Sheets("転記先DB") ' 出力先 '=== 設定値 === Dim colラベル開始列 As Long: colラベル開始列 = 1 ' 開始列 Dim rowラベル開始行 As Long: rowラベル開始行 = 2 ' 開始行 Dim labelWidth As Long: labelWidth = 3 ' ラベル1個の幅(列数) Dim labelHeight As Long: labelHeight = 5 ' ラベル1個の高さ(行数) Dim colラベル最終列 As String: colラベル最終列 = "I" ' ラベルが使用する最終列記号 '=== キーに対する相対位置(行, 列)=== ' ラベルの左上角(キー位置)からの相対位置で定義 Dim dicラベル内のoffset As Object Set dicラベル内のoffset = CreateObject("Scripting.Dictionary") dicラベル内のoffset.Add "氏名", Array(0, 0) ' キー位置そのもの dicラベル内のoffset.Add "生年月日", Array(0, 1) ' キー位置から右に1列 dicラベル内のoffset.Add "性別", Array(0, 2) ' キー位置から右に2列 dicラベル内のoffset.Add "住所", Array(1, 0) ' キー位置から下に1行 dicラベル内のoffset.Add "電話番号", Array(1, 1) ' キー位置から下に1行、右に1列 dicラベル内のoffset.Add "メール", Array(1, 2) ' キー位置から下に1行、右に2列 '=== 出力先をクリア === wsDst.Cells.Clear '=== 見出しを書き出し === Dim colDst As Long: colDst = 1 Dim key As Variant For Each key In dicラベル内のoffset.Keys wsDst.Cells(1, colDst).Value = key colDst = colDst + 1 Next Dim iRowDst As Long: iRowDst = 2 Dim lastRow As Long: lastRow = wsSrc.UsedRange.Rows.Count Dim lastCol As Long: lastCol = wsSrc.Range(colラベル最終列 & "1").Column '=== 縦方向のラベルを処理 === Dim iRowSrc As Long: iRowSrc = rowラベル開始行 Do While iRowSrc <= lastRow '=== 横方向のラベルを処理 === Dim iColSrc As Long: iColSrc = colラベル開始列 Do While iColSrc <= lastCol Dim pos As Variant: pos = dicラベル内のoffset("氏名") Dim is氏名セルに値がある As Boolean is氏名セルに値がある = (Trim(CStr(wsSrc.Cells(iRowSrc, iColSrc).Offset(pos(0), pos(1)).Value)) <> "") ' 氏名が空でない場合のみ処理 If is氏名セルに値がある Then colDst = 1 For Each key In dicラベル内のoffset.Keys pos = dicラベル内のoffset(key) wsDst.Cells(iRowDst, colDst).Value = wsSrc.Cells(iRowSrc, iColSrc).Offset(pos(0), pos(1)).Value colDst = colDst + 1 Next iRowDst = iRowDst + 1 End If iColSrc = iColSrc + labelWidth ' 次のラベル列(横方向) Loop iRowSrc = iRowSrc + labelHeight ' 次のラベル行(縦方向) Loop MsgBox "変換完了: " & (iRowDst - 2) & "件のデータを処理しました。" End Sub

 

 

3 claudeにあれこれ指示した。

 

 

 

 

ダブルクリックしたセルが何列かを判定して○をつけるマクロ ExcelVBA

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    ' ダブルクリックの既定動作をキャンセル
    Cancel = True
    
    ' セルアドレスから列記号を取得
    Dim columnLetter As String
    columnLetter = Split(Target.Address, "$")(1)
    
    ' 指定された列の場合のみ○を設定
    Select Case columnLetter
        Case "A", "C", "Z"
            Target.Value = "○"
    End Select
End