文字列の内容 Left関数

Left関数は文字列を先頭から指定した文字数分だけ取得する関数です。

簡単に言うと文字の抜き取りです。

Left関数の構文

Left( String , Length )

Left( 文字列 , 抜き出したい文字数 )

Left関数の使用例

・Left関数内に文字列を直接設定

・Left関数内に文字列がないの場合

・文字列を変数に設定

・Left関数内で文字列の結合

・セルから文字列を取得して隣のセルに設定

繰り返し処理(for文)

・繰り返し処理(Do While文)

の内容で説明していきます。

Left関数内に文字列を直接設定

Sub Left()
    
    MsgBox Left("abcde", 3)

End Sub

先頭文字から3文字目まで表示されます。

Left関数内に文字列がないの場合

Sub Left1()
    
    MsgBox Left("", 3)

End Sub

文字列がないためメッセージボックス内には何も表示されません。

文字列を変数に設定

Sub Left2()
    Dim str As String
    str = "abcde"
    
    MsgBox Left(str, 3)

End Sub

str = abcdeなので先頭から3文字までのabcが表示されます。

Left関数内で文字列の結合

Sub Left3()
    Dim str As String
    str = "abcde"
    
    MsgBox Left(str + "fgh", 7)

End Sub

Left関数ないの文字列は”abcde”+”fgh”=”abcdefgh”になります。

そこから先頭から7文字なのでabcdefgで表示されます。

問題1

以下の内容を実行したときにメッセージボックスに表示される内容はどの様になりますか。

Sub Left4()
    Dim str As String
    str = "あいうえお"
    
    MsgBox Left(str, 2)

End Sub

問題2

以下の内容を実行したときにメッセージボックスに表示される内容はどの様になりますか。

Sub Left5()
    Dim str1, str2 As String
    str1 = "あいうえお"
    str2 = "かきくけこ"
    
    MsgBox Left(str1 + str2, 2 + 5)

End Sub

問題1の答え

str = “あいうえお”でしたので先頭からの2文字ですので”あい”が表示されます。

問題2の答え

Left(“あいうえお” + “かきくけこ”, 2 + 5)

Left(“あいうえおかきくけこ”, 7)になるため”あいうえおかき”が表示されます。

セルから文字列を取得して隣のセルに設定

B2から文字列を取得してC2に設定します。

Sub Left6()
    Dim str As String
    str = Range("B2").Value
    
    Range("C2").Value = Left(str, 3)

End Sub

処理の実行

abcの値がC2のセルに設定されました。

同様の処理内容

Left関数内にRange(“B2”)を設定する。

Sub Left7()
    
    Range("C2").Value = Left(Range("B2").Value, 3)

End Sub

Rangeではなく、Cellsで設定する。

Sub Left8()
    Dim str As String
    str = Cells(2, 2)
    
    Cells(2, 3) = Left(str, 3)

End Sub

上記、2つの処理でもabcの値がC2のセルに設定されます。

Cellsのイメージ

繰り返し処理(for文)

B列に取得したい文字列が8行入力されています。

これを繰り返し処理でC列に先頭から3文字取得して表示させます。

処理内容

Sub Left9()
    Dim str As String
    Dim i As Integer
    
    For i = 1 To 8
        str = Cells(i + 1, 2)
    
        Cells(i + 1, 3) = Left(str, 3)
    Next

End Sub

処理の結果

8行分先頭から3文字まで取得できました。

しかし、最後から2行の文字列は数値で表示されました。

VBA側で文字列として処理をしてもExcel側で数値に変換されます。

この表示を修正するにはセルの書式設定で文字列として表示させましょう。

これで数値が正常に文字列として表示されます。

繰り返し処理(Do While文)

for文ではFor i = 1 To 8と記載して8回処理をしたら終了する設定にしました。

Do While文では終了条件で繰り返し処理を終了させます。

終了条件はB列が空白になるまで繰り返し処理を行います。

つまりB10まで繰り返し処理を行います。

処理内容

Sub Left10()
    Dim str As String
    Dim i As Integer
    
    i = 1
    
    Do While Cells(i + 1, 2) <> ""
        str = Cells(i + 1, 2)
    
        Cells(i + 1, 3) = Left(str, 3)
        i = i + 1  'この処理が抜けると無限ループになります。
    Loop

End Sub

Do While Cells(i + 1, 2) <> “”で空白でない限り処理を繰り返します。

処理の結果

for文と結果は変わりませんがB列が空白でない限り処理が実行されます。

今回はLeft関数を使用した使用例を複数記載致しました。

皆様の参考になれば幸いです。

次回はRight関数の使用例を投稿致します。

指定したフォルダにあるファイルをコピーしてファイル名を変更して貼り付けの処理内容

前回の内容のファイル名を変更して貼り付けの処理の説明を行います。

ファイル名の変更処理を行っている内容

フォルダを指定してファイルをコピーして、ファイル名を変更して出力先のフォルダに貼り付けを行っています。

処理の説明

メイン処理

Sub サブフォルダ含むファイル名取得()

    Dim maisu As Integer
    Dim strFolderpass As String
    
    '枚数の初期設定をします。
    maisu = 1
    
    '対象フォルダのパスを設定
    strFolderpass = Range("B1").Value
    
    'ファイルのパスの判定
    If strFolderpass = "" Or Range("B2").Value = "" Then
        MsgBox "対象フォルダのパスがありません。パスを入力してください。"
    Else
        'ファイル名変更のメソッドを呼び出します。
        Call ファイル名変更(strFolderpass, maisu)
    End If

End Sub

メイン処理ではB1とB2にパスが指定されているか判定を行い。入力がされていた場合はファイル名変更のメソッドを呼び出します。

ここでのメソッドは自分で作成した関数みたいものです。

ファイル名変更の処理内容

Sub ファイル名変更(strFolderpass As String, maisu As Integer)

    Dim objfFSO As Object
    Dim objFiles As Object
    Dim objFile As Object
    Dim objSubFolders As Object
    Dim objSubFolder As Object
    Dim fileName, file, filePath As String
    Dim kakucho, seko As String
    Dim i As Integer
    Dim syuturyokuPath As String
    
    
    'ファイルやフォルダを操作するオブジェクトの生成
    Set objfFSO = CreateObject("Scripting.FileSystemObject")

    '対象フォルダのファイルオブジェクトをセット
    Set objFiles = objfFSO.GetFolder(strFolderpass).Files
    
    i = 1
    'ファイルをコピーして出力先のフォルダにファイル名を変更して貼り付け
    For Each objFile In objFiles
        file = objFile.Name
        filePath = objFile.Path
        fileName = Mid(filePath, Len(Range("B1")) + 1, Len(filePath) - Len(Range("B1")) - Len(file))
        fileName = Replace(fileName, "\", "_")
        kakucho = Mid(file, InStr(file, "."))
        syuturyokuPath = Range("B2").Value + "\"
        Select Case i Mod 3
            Case 1
                seko = "施工前"
            Case 2
                seko = "施工中"
            Case Else
                seko = "施工後"
        End Select
        FileCopy filePath, syuturyokuPath & maisu & fileName & seko & kakucho
        
        maisu = maisu + 1
        i = i + 1
    Next objFile
    

    '対象フォルダのサブフォルダファイルオブジェクトをセット
    Set objSubFolders = objfFSO.GetFolder(strFolderpass).SubFolders

    'サブフォルダを含むファイル名取得
    For Each objSubFolder In objSubFolders
     
        If objSubFolder.Name <> "" Then
            
            'サブフォルダのパスをメソッドへ渡して再帰的に処理を行う
            Call ファイル名変更(objSubFolder.Path, maisu)
            
        End If
         
    Next objSubFolder

    '使用したオブジェクトの解放
    Set objfFSO = Nothing
    Set objFiles = Nothing
    Set objFile = Nothing
    Set objSubFolders = Nothing
    Set objSubFolder = Nothing

End Sub

上記で行っている処理の内容

受け取ったパス内にファイルが存在する分だけ処理を繰り返す。

ファイルをコピーして出力先のフォルダにファイル名を変更して貼り付け。

受け取ったパス内にフォルダが存在する分だけ処理を繰り返す。

サブフォルダのパスをファイル名変更メソッドに渡す。

    'サブフォルダを含むファイル名取得
    For Each objSubFolder In objSubFolders
     
        If objSubFolder.Name <> "" Then
            
            'サブフォルダのパスをメソッドへ渡して再帰的に処理を行う
            Call ファイル名変更(objSubFolder.Path, maisu)
            
        End If
         
    Next objSubFolder

ファイル名変更()の処理を行っている最中にさらにファイル名変更()を呼び出す処理を再帰処理といいます。要は同じ処理を呼び出しているだけです。

再帰処理のイメージ

ファイルのコピーの内容

    i = 1
    'ファイルをコピーして出力先のフォルダにファイル名を変更して貼り付け
    For Each objFile In objFiles
        file = objFile.Name
        filePath = objFile.Path
        fileName = Mid(filePath, Len(Range("B1")) + 1, Len(filePath) - Len(Range("B1")) - Len(file))
        fileName = Replace(fileName, "\", "_")
        kakucho = Mid(file, InStr(file, "."))
        syuturyokuPath = Range("B2").Value + "\"
        Select Case i Mod 3
            Case 1
                seko = "施工前"
            Case 2
                seko = "施工中"
            Case Else
                seko = "施工後"
        End Select
        FileCopy filePath, syuturyokuPath & maisu & fileName & seko & kakucho
        
        maisu = maisu + 1
        i = i + 1
    Next objFile

フォルダの指定した位置からサブフォルダに含まれるファイルのパスを取得して、フォルダの指定した場所からファイルの間のサブフォルダ名をファイル名に設定しています。

例 

フォルダの指定 C:\Users\nekon\Desktop\仕事\ファイル一覧

ファイルの位置 C:\Users\nekon\Desktop\仕事\ファイル一覧\場所(1)\工事(1)\IMG00012.jpg

ファイル名を取得

file = objFile.Name

file = IMG00012.jpg

ファイルのパスを取得

filePath = objFile.Path

filePath = C:\Users\nekon\Desktop\仕事\ファイル一覧\場所(1)\工事(1)\IMG00012.jpg

コピーしたいファイルのサブフォルダ名の抜き出し

fileName = Mid(filePath, Len(Range(“B1”)) + 1, Len(filePath) – Len(Range(“B1”)) – Len(file))

fileName = \場所(1)\工事(1)\

\を_に変換

fileName = Replace(fileName, “\”, “_”)

fileName = _場所(1)_工事(1)_

拡張子の取得

kakucho = Mid(file, InStr(file, “.”))

kakucho = .jpg

出力先のパスを設定

syuturyokuPath = Range(“B2”).Value + “\”

syuturyokuPath = C:\Users\nekon\Desktop\仕事\Excel一覧\出力先\

施工状況の設定

        Select Case i Mod 3
            Case 1
                seko = "施工前"
            Case 2
                seko = "施工中"
            Case Else
                seko = "施工後"
        End Select

iを3で割った余りで施工前中後を設定している。

ファイル名を変更して貼り付け

FileCopy コピー元のファイルパス , コピー先のファイルパス

FileCopy filePath, syuturyokuPath & maisu & fileName & seko & kakucho

コピー元 = C:\Users\nekon\Desktop\仕事\ファイル一覧\場所(1)\工事(1)\IMG00012.jpg

コピー先 = C:\Users\nekon\Desktop\仕事\Excel一覧\出力先\&1&_場所(1)_工事(1)_&施工前&.jpg

maisuはファイルをコピーした数です。

処理全体の内容

Sub サブフォルダ含むファイル名取得()

    Dim maisu As Integer
    Dim strFolderpass As String
    
    'ファイル名一覧を出力する行番号を指定します。
    maisu = 1
    
    '対象フォルダのパスを設定
    strFolderpass = Range("B1").Value
    
    'ファイルのパスの判定
    If strFolderpass = "" Or Range("B2").Value = "" Then
        MsgBox "対象フォルダのパスがありません。パスを入力してください。"
    Else
        'ファイル名変更のメソッドを呼び出します。
        Call ファイル名変更(strFolderpass, maisu)
    End If

End Sub




Sub ファイル名変更(strFolderpass As String, maisu As Integer)

    Dim objfFSO As Object
    Dim objFiles As Object
    Dim objFile As Object
    Dim objSubFolders As Object
    Dim objSubFolder As Object
    Dim fileName, file, filePath As String
    Dim kakucho, seko As String
    Dim i As Integer
    Dim syuturyokuPath As String
    
    
    'ファイルやフォルダを操作するオブジェクトの生成
    Set objfFSO = CreateObject("Scripting.FileSystemObject")

    '対象フォルダのファイルオブジェクトをセット
    Set objFiles = objfFSO.GetFolder(strFolderpass).Files
    
    i = 1
    'ファイルをコピーして出力先のフォルダにファイル名を変更して貼り付け
    For Each objFile In objFiles
        file = objFile.Name
        filePath = objFile.Path
        fileName = Mid(filePath, Len(Range("B1")) + 1, Len(filePath) - Len(Range("B1")) - Len(file))
        fileName = Replace(fileName, "\", "_")
        kakucho = Mid(file, InStr(file, "."))
        syuturyokuPath = Range("B2").Value + "\"
        Select Case i Mod 3
            Case 1
                seko = "施工前"
            Case 2
                seko = "施工中"
            Case Else
                seko = "施工後"
        End Select
        FileCopy filePath, syuturyokuPath & maisu & fileName & seko & kakucho
        
        maisu = maisu + 1
        i = i + 1
    Next objFile
    

    '対象フォルダのサブフォルダファイルオブジェクトをセット
    Set objSubFolders = objfFSO.GetFolder(strFolderpass).SubFolders

    'サブフォルダを含むファイル名取得
    For Each objSubFolder In objSubFolders
     
        If objSubFolder.Name <> "" Then
            
            'サブフォルダのパスをメソッドへ渡して再帰的に処理を行う
            Call ファイル名変更(objSubFolder.Path, maisu)
            
        End If
         
    Next objSubFolder

    '使用したオブジェクトの解放
    Set objfFSO = Nothing
    Set objFiles = Nothing
    Set objFile = Nothing
    Set objSubFolders = Nothing
    Set objSubFolder = Nothing

End Sub

ファイル名を変更して貼り付け処理の説明を終わります。

今回の内容で写真一括貼り付けの自動化を完了とします。また、処理を思いついたら追加していきます。

次回は文字列を取得してどの様な処理を行えるか記載していきたいと思います。

指定したフォルダにあるファイルをコピーしてファイル名を変更して貼り付け

前回の写真の一括貼り付け処理の内容でファイル名から文字列を取得して各項目に設定する方法を行いました。

そこでVBAが正常に動くか確認を行うため、テストファイルを作成するのに50枚の写真のファイル名を変更致しました。

50枚のファイル名を変更するのに15分ぐらいの時間と簡単な文字の入力を行ったのですが拷問の様な作業に感じたのでフォルダ名を参照しファイル名を自動で変更するマクロを組みました。

ファイル名の変更処理を行っている内容

指定したフォルダの下にある全てのフォルダのファイルからファイルをコピーして、出力先のフォルダにファイル名を変更して貼り付けを行います。

ファイル名の変更内容のルールとしてファイルの数とファルダ名を取得してファイル名に設定しています。

ファイル名のルール 番号_フォルダ名(場所)_フォルダ名(工事)_施工前中後

Excelファイル

フォルダの指定とファイルを貼り付ける位置を設定しています。

フォルダの指定

青枠で囲ってあるフォルダ内の全てのファイルをコピーします。

工事フォルダ全てに3つのファイルを置いてあります。

出力先フォルダ

処理の実行

ファイル名を変更して貼り付け

ファイル一覧フォルダの下にある全てのファイルをコピーして貼り付けています。

ファイル名取得処理の内容

Sub サブフォルダ含むファイル名取得()

    Dim maisu As Integer
    Dim strFolderpass As String
    
    '枚数の初期設定をします。
    maisu = 1
    
    '対象フォルダのパスを設定
    strFolderpass = Range("B1").Value
    
    'ファイルのパスの判定
    If strFolderpass = "" Or Range("B2").Value = "" Then
        MsgBox "対象フォルダのパスがありません。パスを入力してください。"
    Else
        'ファイル名変更のメソッドを呼び出します。
        Call ファイル名変更(strFolderpass, maisu)
    End If

End Sub




Sub ファイル名変更(strFolderpass As String, maisu As Integer)

    Dim objfFSO As Object
    Dim objFiles As Object
    Dim objFile As Object
    Dim objSubFolders As Object
    Dim objSubFolder As Object
    Dim fileName, file, filePath As String
    Dim kakucho, seko As String
    Dim i As Integer
    Dim syuturyokuPath As String
    
    
    'ファイルやフォルダを操作するオブジェクトの生成
    Set objfFSO = CreateObject("Scripting.FileSystemObject")

    '対象フォルダのファイルオブジェクトをセット
    Set objFiles = objfFSO.GetFolder(strFolderpass).Files
    
    i = 1
    'ファイルをコピーして出力先のフォルダにファイル名を変更して貼り付け
    For Each objFile In objFiles
        file = objFile.Name
        filePath = objFile.Path
        fileName = Mid(filePath, Len(Range("B1")) + 1, Len(filePath) - Len(Range("B1")) - Len(file))
        fileName = Replace(fileName, "\", "_")
        kakucho = Mid(file, InStr(file, "."))
        syuturyokuPath = Range("B2").Value + "\"
        Select Case i Mod 3
            Case 1
                seko = "施工前"
            Case 2
                seko = "施工中"
            Case Else
                seko = "施工後"
        End Select
        FileCopy filePath, syuturyokuPath & maisu & fileName & seko & kakucho
        
        maisu = maisu + 1
        i = i + 1
    Next objFile
    

    '対象フォルダのサブフォルダファイルオブジェクトをセット
    Set objSubFolders = objfFSO.GetFolder(strFolderpass).SubFolders

    'サブフォルダを含むファイル名取得
    For Each objSubFolder In objSubFolders
     
        If objSubFolder.Name <> "" Then
            
            'サブフォルダのパスをメソッドへ渡して再帰的に処理を行う
            Call ファイル名変更(objSubFolder.Path, maisu)
            
        End If
         
    Next objSubFolder

    '使用したオブジェクトの解放
    Set objfFSO = Nothing
    Set objFiles = Nothing
    Set objFile = Nothing
    Set objSubFolders = Nothing
    Set objSubFolder = Nothing

End Sub

今回はVBA上からファイル名のコピーをしてファイル名を変更して貼り付けを行いました。

次回は処理の説明を行います。

ファイル名から文字列の取得

写真の一括貼り付けを行う時に写真の貼り付けたい順番とファイル名を決めます。

名前の付け方にルールを決めてファイル名を取得して、セルに値を設定する様に致しました。

ファイル名から文字列を取得して各項目に設定

ファイル名の決め方

ファイル名  1_場所_工事_花(1).jpg

表示したい順番、場所、工事種目、施工状況の間に”_“を設定しています。

今回は”_“を判断材料として使用しているだけです。

判断材料はファイルの命名規則に問題なければ何でも大丈夫です。

例 “.””\”等はファイルの命名上問題が発生します。

写真毎に各項目のセルに値を設定

処理の説明

変数の宣言

    'ファイル名から場所,工事種目,施工状況の変数の宣言
    Dim basyo, koujisyu, sekou As String
    Dim basyoi, koujisyui, sekoui, doti As Integer
    Dim kensakuMoji As String

検索文字の初期設定

    '検索文字の初期設定
    kensakuMoji = "_"

文字列検索

fileにファイル名が設定されています。

        '場所の初期位置を取得
        basyoi = InStr(file, kensakuMoji)
        '工事種目の初期位置を取得
        koujisyui = InStr(basyoi + 1, file, kensakuMoji)
        '施工状況の初期位置を取得
        sekoui = InStr(koujisyui + 1, file, kensakuMoji)
        '.の位置を取得
        doti = InStr(file, ".")

InStrでファイル名にある”_”の位置を取得しています。

各項目のセルに文字列を設定

        '場所のセルに設定
        basyo = Mid(file, basyoi + 1, koujisyui - basyoi - 1)
        Cells(k + 4, j + 13) = basyo
        '工事種目のセルに設定
        koujisyu = Mid(file, koujisyui + 1, sekoui - koujisyui - 1)
        Cells(k + 6, j + 13) = koujisyu
        '施工状況のセルに設定
        sekou = Mid(file, sekoui + 1, doti - sekoui - 1)
        Cells(k + 8, j + 13) = sekou

Midで文字列を抜き出しています。

Cellsで抜き出した値をセルに設定しています。

処理全体の内容

Sub 写真張り付け_Click()
    
    'ループ関数を設定
    Dim i As Integer, j As Integer, k As Integer
    '写真の一覧を取得
    Dim fileName As Variant
    Dim dblscal As Double
    Dim str As String
    
    Dim day As Date
    Dim ObjShell As Object
    Dim ObjFolder As Object
    Dim filePath As Variant
    Dim file As Variant
    
'←--------追加
    'ファイル名から場所,工事種目,施工状況の変数の宣言
    Dim basyo, koujisyu, sekou As String
    Dim basyoi, koujisyui, sekoui, doti As Integer
    Dim kensakuMoji As String
'---------->
  
    Dim startTime As Double
    Dim endTime As Double
    Dim processTime As Double
    
  
    fileName = Application.GetOpenFilename( _
        filefilter:="画像ファイル,*.bmp;*.jpg;*.gif;*.JPG", _
        MultiSelect:=True)
    '画像ファイルを選択しなかった場合は処理を終わらせる
    If Not IsArray(fileName) Then Exit Sub
    
    '処理中画面描写をしない
    Application.ScreenUpdating = False
    
    
'←------追加
    '検索文字の初期設定
    kensakuMoji = "_"
'---------->
    
    '写真を貼る開始セルの列
    j = 2
    '写真を貼る開始セルの行
    k = 2
    
    '印刷範囲の初期設定
    str = Range(Cells(1, 1), Cells(60, 16)).Address
    '原本シートのコピーを末尾に追加
    Worksheets("原本").Copy After:=Worksheets(Worksheets.Count)
    'ボタンを削除
    ActiveSheet.DrawingObjects.Delete
    
    'シェルの設定
    Set ObjShell = CreateObject("Shell.Application")
    
    '取得した写真リストをセルに貼り付け
    For i = LBound(fileName) To UBound(fileName)
        If i <> 1 And i Mod 3 = 1 Then
            Worksheets("原本").Range(str).Copy
            Cells(k - 1, 1).PasteSpecial
            Application.CutCopyMode = False
            ActiveSheet.HPageBreaks.Add before:=Cells(((i \ 3) * 60) + 1, 1)
        End If
        
        '選択ファイル
        With ActiveSheet.Shapes.AddPicture( _
            fileName:=fileName(i), _
            linktofile:=False, _
            savewithdocument:=True, _
            Left:=ActiveCell.Left + 1, _
            Top:=ActiveCell.Top + 1, _
            Width:=ActiveCell.Width * 10, _
            Height:=ActiveCell.Height * 18)
            '結合セルの大きさに設定する場合は下記の内
            'Height:=ActiveCell.MergeArea.Height, _
            'Width:=ActiveCell.MergeArea.Width)
        End With
        
        '写真の貼り直し
        ActiveSheet.Shapes(i).Select
        Selection.Cut
        Cells(k, j).Select
        ActiveSheet.PasteSpecial Format:="図 (JPEG)", Link:=False, DisplayasIcon:=False
        Application.CutCopyMode = False
        
        
        'Noに数を記入
        Cells(k, j + 13) = i
        
        'ファイルのパスを取得
        filePath = Left(fileName(i), InStrRev(fileName(i), "\"))
        'ファイル名の取得
        file = Mid(fileName(i), Len(filePath) + 1)
        
        '写真のデータを参照
        Set ObjFolder = ObjShell.Namespace(filePath).ParseName(file)

        '写真の撮影日を取得
        day = ObjFolder.ExtendedProperty("System.Photo.DateTaken")
        '写真のデータの参照を解放
        Set ObjFolder = Nothing
        '写真の撮影日をセルに設定
        Cells(k + 2, j + 13) = Format(day, "yyyy年m月d日")
        
'←------追加
        '文字列検索
        '場所の初期位置を取得
        basyoi = InStr(file, kensakuMoji)
        '工事種目の初期位置を取得
        koujisyui = InStr(basyoi + 1, file, kensakuMoji)
        '施工状況の初期位置を取得
        sekoui = InStr(koujisyui + 1, file, kensakuMoji)
        '.の位置を取得
        doti = InStr(file, ".")
        '場所のセルに設定
        basyo = Mid(file, basyoi + 1, koujisyui - basyoi - 1)
        Cells(k + 4, j + 13) = basyo
        '工事種目のセルに設定
        koujisyu = Mid(file, koujisyui + 1, sekoui - koujisyui - 1)
        Cells(k + 6, j + 13) = koujisyu
        '施工状況のセルに設定
        sekou = Mid(file, sekoui + 1, doti - sekoui - 1)
        Cells(k + 8, j + 13) = sekou
'-------→
        
        '次のセルの位置を設定する
        k = k + 20
        
    Next i
    
    'シェルの解放
    Set ObjShell = Nothing
    
    i = i - 1
    k = k - 20
    
    Select Case i Mod 3
        Case 1
            str = Range(Cells(1, 1), Cells(k + 58, 16)).Address
        Case 2
            str = Range(Cells(1, 1), Cells(k + 38, 16)).Address
        Case Else
            str = Range(Cells(1, 1), Cells(k + 18, 16)).Address
    End Select
    
    ActiveSheet.PageSetup.PrintArea = str
    
    '写真のズレを修正
    ActiveSheet.Shapes.SelectAll
    Selection.ShapeRange.LockAspectRatio = msoFalse
    Selection.ShapeRange.Height = Cells(2, 2).Height * 18
    Selection.ShapeRange.Width = Cells(2, 2).Width * 10
    

    
    Cells(1, 1).Select
    
    '画面描写を実行
    Application.ScreenUpdating = True
    
End Sub

今回の内容で各項目に値を設定する事が出来ました。

写真の一括貼り付け処理はエクセル上での操作でファイルを取得すれば自動で各項目に設定するため、自動化完了とします。

また、処理など思いつけば機能の追加を行います。

写真の撮影日取得の処理の説明

報告書の作成で写真を撮影した日にち取得する処理の説明を行います。

写真一括貼り付けの追加処理の内容

写真のデータから撮影日を取得してセルに設定しています。

変数の宣言

    Dim day As Date
    Dim ObjShell As Object
    Dim ObjFolder As Object
    Dim filePath As Variant
    Dim file As Variant

シェルの設定

Set ObjShell = CreateObject("Shell.Application")

shellの設定でExcelからファイルの操作を行えるようにします。

ファイルのパスの取得

filePath = Left(fileName(i), InStrRev(fileName(i), "\"))

ファイル名の取得

file = Mid(fileName(i), Len(filePath) + 1)

例として、C:\Users\nekon\Desktop\仕事\写真\IMG00012.jpgの内容がfileName(i)に入っているとします。

fileName(i) = C:\Users\nekon\Desktop\仕事\写真\IMG00012.jpg

ファイルパスの取得は右から”\”の記号を検索して見つけた位置までの情報を設定しています。

InStrRev(fileName(i), “\”)で位置を検索して29の数値が見つかります。

Left(fileName(i), InStrRev(fileName(i), “\”))

Left(fileName(i), 29)になり

Left(fileName(i), 29) は C:\Users\nekon\Desktop\仕事\写真\ となります。

filePath = Left(fileName(i), 29)

filePath = C:\Users\nekon\Desktop\仕事\写真\

ファイル名の取得はfileName(i)からfilePathの内容を抜いた文字列を設定しています。

C:\Users\nekon\Desktop\仕事\写真\IMG00012.jpgから

C:\Users\nekon\Desktop\仕事\写真\を抜いて

IMG00012.jpgを設定しています。

写真データの参照

Set ObjFolder = ObjShell.Namespace(filePath).ParseName(file)

写真の撮影日を取得

day = ObjFolder.ExtendedProperty("System.Photo.DateTaken")

写真のデータの参照を解放

Set ObjFolder = Nothing

セルに撮影日を設定

Cells(k + 2, j + 13) = Format(day, "yyyy年m月d日")

シェルの解放

Set ObjShell = Nothing

写真一括貼り付け処理

Sub 写真張り付け_Click()
    
    'ループ関数を設定
    Dim i As Integer, j As Integer, k As Integer
    '写真の一覧を取得
    Dim fileName As Variant
    Dim dblscal As Double
    Dim str As String
    
'←--------追加
    Dim day As Date
    Dim ObjShell As Object
    Dim ObjFolder As Object
    Dim filePath As Variant
    Dim file As Variant
    
'---------->
  
    Dim startTime As Double
    Dim endTime As Double
    Dim processTime As Double
    
  
    fileName = Application.GetOpenFilename( _
        filefilter:="画像ファイル,*.bmp;*.jpg;*.gif;*.JPG", _
        MultiSelect:=True)
    '画像ファイルを選択しなかった場合は処理を終わらせる
    If Not IsArray(fileName) Then Exit Sub
    
    '処理中画面描写をしない
    Application.ScreenUpdating = False
    
    '開始時間取得
    startTime = Timer
    
    
    '写真を貼る開始セルの列
    j = 2
    '写真を貼る開始セルの行
    k = 2
    
    '印刷範囲の初期設定
    str = Range(Cells(1, 1), Cells(60, 16)).Address
    '原本シートのコピーを末尾に追加
    Worksheets("原本").Copy After:=Worksheets(Worksheets.Count)
    'ボタンを削除
    ActiveSheet.DrawingObjects.Delete
    
    
'←--------追加
    'シェルの設定
    Set ObjShell = CreateObject("Shell.Application")
'-------→
    
    
    '取得した写真リストをセルに貼り付け
    For i = LBound(fileName) To UBound(fileName)
        If i <> 1 And i Mod 3 = 1 Then
            Worksheets("原本").Range(str).Copy
            Cells(k - 1, 1).PasteSpecial
            Application.CutCopyMode = False
            ActiveSheet.HPageBreaks.Add before:=Cells(((i \ 3) * 60) + 1, 1)
        End If
        
        '選択ファイル
        With ActiveSheet.Shapes.AddPicture( _
            fileName:=fileName(i), _
            linktofile:=False, _
            savewithdocument:=True, _
            Left:=ActiveCell.Left, _
            Top:=ActiveCell.Top, _
            Width:=ActiveCell.Width * 10, _
            Height:=ActiveCell.Height * 18)
            '結合セルの大きさに設定する場合は下記の内
            'Height:=ActiveCell.MergeArea.Height, _
            'Width:=ActiveCell.MergeArea.Width)
        End With
        
        '写真の貼り直し
        ActiveSheet.Shapes(i).Select
        Selection.Cut
        Cells(k, j).Select
        ActiveSheet.PasteSpecial Format:="図 (JPEG)", Link:=False, DisplayasIcon:=False
        Application.CutCopyMode = False
        
        
        'Noに数を記入
        Cells(k, j + 13) = i
        
'←------追加
        'ファイルのパスを取得
        filePath = Left(fileName(i), InStrRev(fileName(i), "\"))
        'ファイル名の取得
        file = Mid(fileName(i), Len(filePath) + 1)
        
        '写真のデータを参照
        Set ObjFolder = ObjShell.Namespace(filePath).ParseName(file)

        '写真の撮影日を取得
        day = ObjFolder.ExtendedProperty("System.Photo.DateTaken")
        '写真のデータの参照を解放
        Set ObjFolder = Nothing
        Cells(k + 2, j + 13) = Format(day, "yyyy年m月d日")
        
'-------→
        
        '次のセルの位置を設定する
        k = k + 20
        
    Next i
    
'←--------追加
    'シェルの解放
    Set ObjShell = Nothing
'-------→
    
    i = i - 1
    k = k - 20
    
    Select Case i Mod 3
        Case 1
            str = Range(Cells(1, 1), Cells(k + 58, 16)).Address
        Case 2
            str = Range(Cells(1, 1), Cells(k + 38, 16)).Address
        Case Else
            str = Range(Cells(1, 1), Cells(k + 18, 16)).Address
    End Select
    
    ActiveSheet.PageSetup.PrintArea = str
    
    '写真のズレを修正
    ActiveSheet.Shapes.SelectAll
    Selection.ShapeRange.LockAspectRatio = msoFalse
    Selection.ShapeRange.Height = Cells(2, 2).Height * 18
    Selection.ShapeRange.Width = Cells(2, 2).Width * 10
    
    '終了時間取得
    endTime = Timer
    
    '処理時間表示
    processTime = endTime - startTime
    MsgBox "処理時間:" & processTime
    
    Cells(1, 1).Select
    
    '画面描写を実行
    Application.ScreenUpdating = True
    
End Sub

写真一括貼り付けの撮影日を取得の処理内容の説明でした。

次回はさらに機能の追加を致します。

写真の撮影日の取得機能の追加

報告書の作成で写真の貼り付ける場合は撮影した日時を記載する事が多いため、写真データから撮影日の取得機能を追加致しました。

写真の撮影日を日程の隣のセルに表示する様に設定

撮影日が日程の隣のセルに表示されています。

写真を複数枚選択しても写真毎に撮影日を取得

選択しているファイルの撮影日が表示されています。

写真貼り付けの処理(撮影日を取得を追加)

Sub 写真張り付け_Click()
    
    'ループ関数を設定
    Dim i As Integer, j As Integer, k As Integer
    '写真の一覧を取得
    Dim fileName As Variant
    Dim dblscal As Double
    Dim str As String
    
'←--------追加
    Dim day As Date
    Dim ObjShell      As Object
    Dim ObjFolder     As Object
    Dim filePath As Variant
    Dim file As Variant
    
'---------->
    
    fileName = Application.GetOpenFilename( _
        filefilter:="画像ファイル,*.bmp;*.jpg;*.gif;*.JPG", _
        MultiSelect:=True)
    '画像ファイルを選択しなかった場合は処理を終わらせる
    If Not IsArray(fileName) Then Exit Sub
    
    '処理中画面描写をしない
    Application.ScreenUpdating = False
    
    '写真を貼る開始セルの列
    j = 2
    '写真を貼る開始セルの行
    k = 2
    
    '印刷範囲の初期設定
    str = Range(Cells(1, 1), Cells(60, 16)).Address
    '原本シートのコピーを末尾に追加
    Worksheets("原本").Copy After:=Worksheets(Worksheets.Count)
    'ボタンを削除
    ActiveSheet.DrawingObjects.Delete
    
    
'←--------追加
    'シェルの機能の参照
    Set ObjShell = CreateObject("Shell.Application")
'-------→
    
    
    '取得した写真リストをセルに貼り付け
    For i = LBound(fileName) To UBound(fileName)
        If i <> 1 And i Mod 3 = 1 Then
            Worksheets("原本").Range(str).Copy
            Cells(k - 1, 1).PasteSpecial
            Application.CutCopyMode = False
            ActiveSheet.HPageBreaks.Add before:=Cells(((i \ 3) * 60) + 1, 1)
        End If
        
        '選択ファイル
        With ActiveSheet.Shapes.AddPicture( _
            fileName:=fileName(i), _
            linktofile:=False, _
            savewithdocument:=True, _
            Left:=ActiveCell.Left, _
            Top:=ActiveCell.Top, _
            Width:=ActiveCell.Width * 10, _
            Height:=ActiveCell.Height * 18)
            '結合セルの大きさに設定する場合は下記の内
            'Height:=ActiveCell.MergeArea.Height, _
            'Width:=ActiveCell.MergeArea.Width)
        End With
        
        '写真の貼り直し
        ActiveSheet.Shapes(i).Select
        Selection.Cut
        Cells(k, j).Select
        ActiveSheet.PasteSpecial Format:="図 (JPEG)", Link:=False, DisplayasIcon:=False
        Application.CutCopyMode = False
        
        
        'Noに数を記入
        Cells(k, j + 13) = i
        
'←------追加
        'ファイルのパスを取得
        filePath = Left(fileName(i), InStrRev(fileName(i), "\"))
        'ファイル名の取得
        file = Mid(fileName(i), Len(filePath) + 1)
        
        '写真のデータを参照
        Set ObjFolder = ObjShell.Namespace(filePath).ParseName(file)

        '写真の撮影日を取得
        day = ObjFolder.ExtendedProperty("System.Photo.DateTaken")
        '写真のデータの参照を解放
        Set ObjFolder = Nothing
        Cells(k + 2, j + 13) = Format(day, "yyyy年m月d日")
        
'-------→
        
        '次のセルの位置を設定する
        k = k + 20
        
    Next i
    
'←--------追加
    'シェルの解放
    Set ObjShell = Nothing
'-------→
    
    i = i - 1
    k = k - 20
    
    Select Case i Mod 3
        Case 1
            str = Range(Cells(1, 1), Cells(k + 58, 16)).Address
        Case 2
            str = Range(Cells(1, 1), Cells(k + 38, 16)).Address
        Case Else
            str = Range(Cells(1, 1), Cells(k + 18, 16)).Address
    End Select
    
    ActiveSheet.PageSetup.PrintArea = str
    
    '写真のズレを修正
    ActiveSheet.Shapes.SelectAll
    Selection.ShapeRange.LockAspectRatio = msoFalse
    Selection.ShapeRange.Height = Cells(2, 2).Height * 18
    Selection.ShapeRange.Width = Cells(2, 2).Width * 10
    
    Cells(1, 1).Select
    
    '画面描写を実行
    Application.ScreenUpdating = True
    
End Sub

処理の追加部分は←—-追加と表記しています。

次回は追加部分の処理の説明を行います。

改ページの挿入と印刷範囲を設定について

資料を作成した時に印刷範囲の設定や改ページを挿入したりするので今回はこちらを紹介します。

VBAでの改ページや印刷範囲の設定方法

改ページの設定

ActiveSheet.HPageBreaks.Add before:=Cells(挿入したい位置)

印刷範囲の設定

ActiveSheet.PageSetup.PrintArea = Range(Cells(印刷設定したい初期位置), Cells(印刷設定したい範囲)).Address

50枚の写真を読み込ませて処理の実行

写真3枚毎に改ページを挿入する様に設定

改ページの処理内容

            ActiveSheet.HPageBreaks.Add before:=Cells(((i \ 3) * 60) + 1, 1)

印刷範囲の設定

50枚写真を読み込んでいるため51枚目は空白

印刷範囲の処理内容

    Select Case i Mod 3
        Case 1
            str = Range(Cells(1, 1), Cells(k + 58, 16)).Address
        Case 2
            str = Range(Cells(1, 1), Cells(k + 38, 16)).Address
        Case Else
            str = Range(Cells(1, 1), Cells(k + 18, 16)).Address
    End Select
    
    ActiveSheet.PageSetup.PrintArea = str

写真の枚数に合わせて印刷範囲を設定する事も可能

処理内容

    str = Range(Cells(1, 1), Cells(k + 18, 16)).Address
    
    ActiveSheet.PageSetup.PrintArea = str

写真一括貼り付け処理の改ページの挿入と印刷範囲の設定箇所

Sub 写真張り付け_Click()
    
    'ループ関数を設定
    Dim i As Integer, j As Integer, k As Integer
    
    Dim FileName As Variant
    Dim dblscal As Double
    Dim str As String
  
    Dim startTime As Double
    Dim endTime As Double
    Dim processTime As Double

  
    '写真の一覧を取得
    FileName = Application.GetOpenFilename( _
        filefilter:="画像ファイル,*.bmp;*.jpg;*.gif;*.JPG", _
        MultiSelect:=True)
    '写真ファイルを選択しなかった場合は処理を終わらせる
    If Not IsArray(FileName) Then Exit Sub
    
    '処理中画面描写をしない
    Application.ScreenUpdating = False
    
    '開始時間取得
    startTime = Timer
    
    
    '写真を貼る開始セルの列
    j = 2
    '写真を貼る開始セルの行
    k = 2
    
    '印刷範囲の初期設定
    str = Range(Cells(1, 1), Cells(60, 16)).Address
    '原本シートのコピーを末尾に追加
    Worksheets("原本").Copy After:=Worksheets(Worksheets.Count)
    'ボタンを削除
    ActiveSheet.DrawingObjects.Delete
    
    '取得した写真リストをセルに貼り付け
    For i = LBound(FileName) To UBound(FileName)
        If i <> 1 And i Mod 3 = 1 Then
            Worksheets("原本").Range(str).Copy
            Cells(k - 1, 1).PasteSpecial
            Application.CutCopyMode = False

'←-------------改ページの挿入
            ActiveSheet.HPageBreaks.Add before:=Cells(((i \ 3) * 60) + 1, 1)
'-----------------→

        End If
        Cells(k, j).Select
        
        '選択ファイル
        With ActiveSheet.Shapes.AddPicture( _
            FileName:=FileName(i), _
            linktofile:=False, _
            savewithdocument:=True, _
            Left:=ActiveCell.Left, _
            Top:=ActiveCell.Top, _
            Width:=ActiveCell.Width * 10, _
            Height:=ActiveCell.Height * 18)
            '結合セルの大きさに設定する場合は下記の内
            'Height:=ActiveCell.MergeArea.Height, _
            'Width:=ActiveCell.MergeArea.Width)
        End With
        
        '写真の貼り直し
        ActiveSheet.Shapes(i).Select
        Selection.Cut
        ActiveSheet.PasteSpecial Format:="図 (JPEG)", Link:=False, DisplayasIcon:=False
        Application.CutCopyMode = False
        
        
        'Noに数を記入
        Cells(k, j + 13) = i
        
        '次のセルの位置を設定する
        k = k + 20
        
    Next i
        
    i = i - 1
    k = k - 20
    
'←--------------------------------------
    '印刷範囲を設定
    Select Case i Mod 3
        Case 1
            str = Range(Cells(1, 1), Cells(k + 58, 16)).Address
        Case 2
            str = Range(Cells(1, 1), Cells(k + 38, 16)).Address
        Case Else
            str = Range(Cells(1, 1), Cells(k + 18, 16)).Address
    End Select
    
'    str = Range(Cells(1, 1), Cells(k + 18, 16)).Address
    
    ActiveSheet.PageSetup.PrintArea = str
'----------------------------------→
    
    '写真のズレを修正
    ActiveSheet.Shapes.SelectAll
    Selection.ShapeRange.LockAspectRatio = msoFalse
    Selection.ShapeRange.Height = Cells(2, 2).Height * 18
    Selection.ShapeRange.Width = Cells(2, 2).Width * 10
    
    '終了時間取得
    endTime = Timer
    
    '処理時間表示
    processTime = endTime - startTime
    MsgBox "処理時間:" & processTime
    
    Cells(1, 1).Select
    
    '画面描写を実行
    Application.ScreenUpdating = True
    
End Sub

今回も処理の内容を説明させて頂きました。

次回は処理全体の流れを説明します。

写真の一括貼り付けVBA

作業報告書などで写真の貼り付けて提出などの作業は、色々と利用するため今回はこちらを紹介します。

ボタン押下時の実行内容

・貼り付けたい写真の一覧を選択

・印刷範囲を設定しながら写真を指定の位置に貼り付け

今回のポイント

・貼り付け時に写真データの縮小を行っているため、ファイルの容量が少なくしている事

・改ページを挿入しているため、写真の貼り付け後にすぐに印刷が可能な点

Excelファイル

処理の順番の説明

・写真の取り込み

・シートをコピーして末尾に追加

・指定の位置に貼り付け

・写真容量が大きいのでデータの縮小のためJPEGで貼り直し

・写真のNoをセルに記入

・写真の大きさをセルに合わせる

・印刷範囲の設定

処理の実行

印刷範囲を設定しているので印刷もすぐに可能

写真張り付けボタン押下時の処理

Sub 写真張り付け_Click()
    
    'ループ関数を設定
    Dim i As Integer, j As Integer, k As Integer
    Dim FileName As Variant
    Dim dblscal As Double
    Dim str As String
  
   '写真の一覧を取得
    FileName = Application.GetOpenFilename( _
        filefilter:="画像ファイル,*.bmp;*.jpg;*.gif;*.JPG", _
        MultiSelect:=True)
    '写真ファイルを選択しなかった場合は処理を終わらせる
    If Not IsArray(FileName) Then Exit Sub
    
    '処理中画面描写をしない
    Application.ScreenUpdating = False
        
    '写真を貼る開始セルの列
    j = 2
    '写真を貼る開始セルの行
    k = 2
    
    '印刷範囲の初期設定
    str = Range(Cells(1, 1), Cells(60, 16)).Address
    '原本シートのコピーを末尾に追加
    Worksheets("原本").Copy After:=Worksheets(Worksheets.Count)
    'ボタンを削除
    ActiveSheet.DrawingObjects.Delete
    
    '取得した写真リストをセルに貼り付け
    For i = LBound(FileName) To UBound(FileName)
        If i <> 1 And i Mod 3 = 1 Then
            Worksheets("原本").Range(str).Copy
            Cells(k - 1, 1).PasteSpecial
            Application.CutCopyMode = False
            ActiveSheet.HPageBreaks.Add before:=Cells(((i \ 3) * 60) + 1, 1)
        End If

        Cells(k, j).Select
        
        '選択ファイル
        With ActiveSheet.Shapes.AddPicture( _
            FileName:=FileName(i), _
            linktofile:=False, _
            savewithdocument:=True, _
            Left:=ActiveCell.Left, _
            Top:=ActiveCell.Top, _
            Width:=ActiveCell.Width * 10, _
            Height:=ActiveCell.Height * 18)
            '結合セルの大きさに設定する場合は下記の内容
            'Height:=ActiveCell.MergeArea.Height, _
            'Width:=ActiveCell.MergeArea.Width)
        End With
        
        ActiveSheet.Shapes(i).Select
        Selection.Cut
        ActiveSheet.PasteSpecial Format:="図 (JPEG)", Link:=False,DisplayasIcon:=False
        Application.CutCopyMode = False
        
        
        'Noに数を記入
        Cells(k, j + 13) = i
        
        '次のセルの位置を設定する
        k = k + 20
        
    Next i
    
    'コピー範囲を解放
    
    i = i - 1
    k = k - 20
    
    Select Case i Mod 3
        Case 1
            str = Range(Cells(1, 1), Cells(k + 58, 16)).Address
        Case 2
            str = Range(Cells(1, 1), Cells(k + 38, 16)).Address
        Case Else
            str = Range(Cells(1, 1), Cells(k + 18, 16)).Address
    End Select
    
    ActiveSheet.PageSetup.PrintArea = str
    
    
    ActiveSheet.Shapes.SelectAll
    Selection.ShapeRange.LockAspectRatio = msoFalse
    Selection.ShapeRange.Height = Cells(2, 2).Height * 18
    Selection.ShapeRange.Width = Cells(2, 2).Width * 10
    
    Cells(1, 1).Select
    
    '画面描写を実行
    Application.ScreenUpdating = True
    
End Sub


今回は上記のコードを実行した場合に行われる流れを確認していただきました。処理内容の解説は後日行います。