AddPictureメソッドの第2、3引数の組み合わせ確認テスト

お知らせ記事には広告が含まれておりますがExcelのスキルUPに繋がる様コンテンツ自体は手を抜かずに作成しております

Addpictureメソッドの引数を使ってテストを実施

VBAで画像を取り扱う時に活躍するコードとしてAddPictureメソッドが挙げられます。

Shapesプロパティに属しているメソッドです。

私は画像と言えばこのコードを使っています。ものすごく便利ですが難点もあります。

  • 引数が多い
  • 引数を全部指定しないとエラーになる
  • 引数の組み合わせでエラーになる
  • 内容自体が難しい引数もある

この中で「引数の組み合わせでエラーになる」と「内容自体が難しい引数」を取り上げます。

LinkToFileとSaveWithDocumentという引数について解説します。

EnjoyExcel
EnjoyExcel

この引数は共にFalseを指定するとエラーになります。

加えて引数の内容自体が難しいのでうまく使いこなせている人は少ないです。

以降で全通りの組み合わせをテストしてみます。

関連記事

2つの引数が両方ともFalseの時は実行時エラーとなります。

今回の組み合わせテストから除外しています。詳細はこちらの記事をご覧ください。

引数の組み合わせテスト

2つの引数を3つの組み合わせでテストします。

引数\CaseCase1Case2Case3
LinkToFileFalseTrueTrue
SaveWithDocumentTrueFalseTrue
Case1からCase3を使ってトライを行います。

冒頭申し上げました様に共にFalseを指定するとエラーになるのでテスト対象からは外しています。

テスト環境

以下のようなテスト環境を用意しました。

フォルダ&画像

1つのフォルダ内に1つのフォルダを用意しました。あえて階層構造にしています。

画像の正確な枚数は2,184枚です。

気にしたのはフォルダの階層構造です。

画像で言うと黄色のフォルダは増やしても全て周回してくれるコードにしておきました。

2層までは対応します。

セルA3に階層のTOPにくるフォルダのパスを書いてください。

画像ではシルバーのフォルダ(階層のTOPにくるフォルダ)です。

これで全てのフォルダ内を周回出来る様にしてあります。

続いてフォルダの中の画像です。画像名の見た目が悪いですが流してください。

今回は画像名の中に含まれているkaizenというキーワードをもとに画像をExcelに引っ張ります。

全ての画像にKaizenというキーワードは居ます。結局全部の画像を持ってくることになります。

Like演算子を使ったマッチングのコードを入れたかったのでこの様な仕様になっています。

Like演算子では *kaizen* というパターンと画像名を照合・・・というコードを書いています。

画像の大きさは1200×630ピクセル、容量は40KB/枚です。

ワークシート

シートのセルの中に丁度良く収まる様に画像を置く事にします。

セルの大きさは高さ100、幅20です。そんなに大きくないです。

取得したデータの並びとしてはセルA5を起点にA列に画像が並ぶ仕様にしています。

フォルダへのアクセス方法としてはセルのA3にTOPフォルダのパスを書いています。

コードの実行についてはVBEから実行もしくはワークシートにボタンを作ってください。

コード

こちらの記事で使用したコードを加工しています。

今回はLinkToFileとSaveWithDocumentという引数の値を組み変えてるトライをしています。

※該当のTOPフォルダまでのパスはセルA3に書いてください。

Sub AddPictureメソッドの引数組み合わせTRY()
 
'1_変数の宣言
Dim base_path As String 'ファイルパスを格納 セルA3の値に¥をつけた
Dim file_name As String  'ファイル名を格納
Dim file_path As String  '上2つの変数をセットにしたもの
Dim i As Long: i = 2 ' 貼付け位置を管理する変数
Dim FSO As Object ' ファイルシステムオブジェクト フォルダを扱う為の変数
Dim s_fd As Object  '現状掴んでるフォルダを格納する変数
Dim rng As Range '貼り付けるセルを決める為の変数
 
'***********************************************
'2_画面更新をコントロール(少しでも作業を減らして速度を上げる為)
Application.ScreenUpdating = False
'***********************************************
 
    '3_フォルダ周回用のループを作成
    'ファイルシステムオブジェクトはオブジェクトなのでSetが必要
    Set FSO = CreateObject("Scripting.FileSystemObject")
    'セルA3に書いてあるパスに存在するフォルダの中に居るフォルダを順番に選択
    For Each s_fd In FSO.GetFolder(Cells(3, 1)).subfolders
     
      'file_pathを作る為の準備
        base_path = s_fd & "\"
        file_name = Dir(base_path, vbNormal)
        file_path = base_path & file_name
 
        '4_ファイル名のキーワードを確認
        '変数file_nameが無くなるまでループします
        Do Until file_name = ""
            '変数file_name と *kaizen* は一致するのか?
            If file_name Like "*kaizen*" Then
            
               '5_画像を貼り付けるセルを変数rngにセット
              Set rng = Cells(i + 3, 1)
                
               '6_画像を取得する
               'AddPictureメソッドを使う
               '1回引数を指定しないといけないので
               'LeftTopはセル起点、widthHeightはゼロで仮置き
              With rng.Worksheet.Shapes.AddPicture(Filename:=file_path, _
                                                 LinkToFile:=False, _
                                                 SaveWithDocument:=True, _
                                                 Left:=rng.Left, _
                                                 Top:=rng.Top, _
                                                 Width:=0, _
                                                 Height:=0)
                                                                                                                         
                    'Shapeプロパティへの処理
                    .LockAspectRatio = True '縦横比固定
                    .Placement = xlMoveAndSize '移動&サイズ変更
                    '縦を元のサイズを起点に100% = 元の画像と同じサイズ
                    .ScaleHeight 1, msoTrue 
                    '横を元のサイズを起点に100% = 元の画像と同じサイズ
                    .ScaleWidth 1, msoTrue 
                 
                    '7_画像がセルの中心に来る様に大きさを調整
                    '画像のサイズがセルの「幅-2」より大きかったら・・・
                    If .Width > rng.Width - 2 Then  
                        '画像の幅はセル「幅-2」に変更する
                        .Width = rng.Width - 2  
                    End If
                    '画像のサイズがセルの「高さ-2」より大きかったら・・・ 
                    If .Height > rng.Height - 2 Then
                        '画像の幅はセル「高さ-2」に変更する
                        .Height = rng.Height - 2   
                    End If
                    '画像をセル高さ方向の中心にセット        
                    .Top = .Top + ((rng.Height - .Height) / 2) 
                     '画像をセル幅方向の中心にセット
                    .Left = .Left + ((rng.Width - .Width) / 2) 
                         
                End With
     
                i = i + 1
             
            End If
            '8_次の画像を確認する為の処理
            'Dir関数でフォルダ内に居る次のファイルを掴む
            'ファイル名を変数file_nameにセット
            file_name = Dir()
            '変数file_pathに次のファイル名をセットする
            file_path = base_path & file_name
             
        'Doまで戻る
        Loop
     
    Next s_fd
 
'***********************************************
'2_画面更新を止める を解除
Application.ScreenUpdating = True
'***********************************************
 
'9_作業終了の報告
MsgBox "処理が完了しました", , "作業完了"
 
End Sub

このコードではLinkToFileがFalse、SaveWithDocumentはTrueを指定しています。

Addpictureメソッドの引数一覧

次にAddPictureメソッドの引数をおさらいしておきましょう。

番号引 数内 容
1Filename対象データのフルパス
2LinkToFile簡単に言うとTrueでリンク、Falseで画像自体(独立したコピーを生成)
3SaveWithDocument簡単に言うとTrueで画像として保存Falseでリンク情報を保存
4Left文書の左上隅を基準に対象データの左上隅の位置をポイントで指定
5Top文書の上端を基準に対象データの上端をポイントで指定
6Width対象データの横幅を指定
7Height対象データの高さ方向の幅を指定
沢山ある引数は省略出来ない様です。面倒ですがひとまず何かしらの値を入力する必要がありそうです。
LinkToFile

Trueの時はリンク付きの画像が用意されます。

エクセルを起動する度に元データを読み込める様になります。

Falseの時は元データからコピーされた独立した画像だけを取得します。

もう少し分かり易い様に事例を用意したのでご覧ください。

この作業はLinkToFileがTrueの時に画像に何が起きるのかを再現しています。

LinkToFileをTrueにして事前にExcel側に画像を取得しておきます。

その後保存してワークブックを閉じてから以下の順番で作業をしてみます。

  1. フォルダ内の画像を1つ選択
  2. 選択した画像を加工する
  3. 加工した画像を保存する
  4. 再度Excelを開くと事前に取得した画像に加工が反映されている

1、フォルダ内の画像を1つ選択

2、選択した画像を加工する

3、加工した画像を保存する

画像加工後のフォルダ内です。画像が加工されたことが分かります。

4、再度Excelを開くと事前に取得した画像に加工が反映されている

画像が保存されているデータを開くと画像の加工が反映されています。リンクが活きている証拠です。

このように元データとつながった状態で画像を取得出来るのがTrueの状態です。

Falseはコピーされたリンクの無い独立した画像ですのでこのような事は起きません。

SaveWithDocument

Trueは画像を保存、Falseはリンクを保存です。

テスト結果

画像取得後のExcelの容量に差が出ました。

実行後は画像の縦横比を守りつつセルに収まる最大の大きさで画像がセットされます。

2000枚以上の画像を取得するのに要する時間は私のPCで13秒±1秒でした。

(どの組み合わせでも大差なし)

コード実行後
実行後の画面です。セルに画像が並んでいます。セルA3はファイルパスにモザイクをかけています。

マトリクスで表示

結果をテーブルにまとめました。

この結果からすると保存後のデータ量に差が出るのはリンクの有無ではないかと想定されます。

元のデータから切り離してExcelに画像を持ってきた方が保存する際のデータは軽い様です。

2つの引数で共にTrueを選択すると画像で保存しつつ画像のリンクも用意されます。

容量としては1番多くなることも分かりました。

要素Case1Case2Case3
LinkToFileの引数FalseTrueTrue
SaveWithDocumentの引数TrueFalseTrue
仕様独立した画像として
取得後画像を保存
画像とリンクを取得して
リンクを保存
画像とリンクを取得後
画像とリンクを保存
実行時間(秒)差無差無差無
起動・保存(秒)差無差無差無
Excelの容量(KB)144166172
備考大量の画像を
扱う時おすすめ
元画面変更すると
Excelデータも変更
元画面変更すると
Excelデータも変更
実行時間と起動・保存はPC毎に差がありますのであえて書きません。3つの処理には大きな差はありませんでした。

結果的にCase2と3は起動時が同じ動きでした。

どちらもリンクを持ったデータなので起動時に画像を読み込んでから立ち上がります。

以下の様に画像が表示されない状態でExcelが起動されます。

その後数秒して画像が追いかけてくるように表示されました。

ファイル起動時
ファイルリンクがある時はファイル起動時に画像が表示されるまで少し時間がかかります。セルA3はファイルパスにモザイクをかけています。

傾向

それぞれのデータを見て気付いた事を書きます。

LinkToFileをLTF、SaveWithDocumentをSWDで表記します。

LTF:True_SWD:True

容量は重くなるのでデメリットばかりのように感じますがメリットもあります。

元データとリンクが繋がっていますので元データをメンテするとExcel内の画像も更新されます。

LTF:True_SWD:False

両引数共にTrueの時とそんなに差は無いです。

LTFがTrueならSWDはそんなに意識しなくても良いかもしれません。

こちらも元データに変更が入るとExcelに取り込んだデータも変更されます。

ただし容量に差が出るので同じ動きならこちらを使った方が良いという見方もあります。

LTF:False_SWD:True

実質これ1択。PC次第ですが2,000枚以上の画像でも10秒少しでExcelに引っ張ってこれました。

そうなるとリンクを持っておかなくても欲しい時に都度取得した方が取り回しが楽です。

私はこの組み合わせが一番良かったです。

LTF:False_SWD:False

コードとしては書けるしエラーでもないのでコンパイルエラーにはなりません。

実行時に矛盾が生じたので実行時エラーになっているはずですが詳しい事は分かりませんでした。

冒頭のリンク記事で詳しく解説しています。引数の状態からエラーを推測しています。

まとめ

AddPictureメソッドの引数LinkToFileとSaveWithDocumentについて解説しました。

これで用途によって引数を使い分けていただく事が出来るようになりました。

私最初にAddPictureメソッドを使った時は1回説明を読んだだけでは理解出来ませんでした。

しかし自身でコードを使ってマクロを実行して結果を見る事で理解が進みました。

マクロを書ける様になるには自分で試行錯誤する事が一番の近道です。

人に聞く方が早いのですが知識の定着具合という軸で考えると自力に勝るものは無いです。

今回のコードはフォルダと画像だけ用意いただければコードはコピペで使用出来ます。

色々試してみて下さい。

EnjoyExcel

タイトルとURLをコピーしました