ユーザーフォームとPropertyプロシージャと私

ユーザーフォームにプロパティを追加する

フォームモジュールにPropertyプロシージャを書いてみる

なんかこう、クラスモジュールとフォームモジュールの違いが分からなくなってきている私です。

akashi-keirin.hatenablog.com

コチラに、id:imihito さんからいただいたコメントへの返信を書いているときにふっと思いついたのが、

フォームモジュールにPropertyプロシージャ書いたらどうなるんだろ?
フォームモジュールにもフィールド持たせたりできんの?


ということだった。

で、実験。

前回記事のリスト1に、次のように追加。

リスト1 フォームモジュール
Option Explicit

Private secretName_ As String    '……(1)'

Public Property Let secretName(n As String)    '……(2)'
  secretName_ = n
End Property

Public Property Get secretName() As String    '……(3)'
  secretName = secretName_
End Property

Public Sub init(ByVal formCaption As String, _
                ByVal btnLeftName As String, _
                ByVal btnCenterName As String, _
                ByVal btnRightName As String)
  With Me
    .Caption = formCaption
    .BtnLeft.Caption = btnLeftName
    .BtnCenter.Caption = btnCenterName
    .BtnRight.Caption = btnRightName
  End With

(1)の

Private secretName_ As String

インスタンス変数。コイツに値(文字列)を持たせることで、インスタンスごとに固有の名前を持たせることができる。(もちろん、あまり実用上意味はないけど、あくまでも説明用のパラメータです。)

(2)からの3行

Public Property Let secretName(n As String)
  secretName_ = n
End Property

はsetterメソッド。「[インスタンス].secretName = "○○"」の形で値を設定することができる。

(3)からの3行

Public Property Get secretName() As String
  secretName = secretName_
End Property

はgetterメソッド。「[インスタンス].secretName = "○○"」の形で値を返す。

生まれ変わったUserFormTemplateオブジェクトを使ってみる。

前回記事のリスト2に次のようにコードを追加する。

スト2 標準モジュール
Public Sub userFormTest()
  Dim uFrm As UserFormTemplate
  Set uFrm = New UserFormTemplate
  With uFrm
    .init "アホ", "ボケ", "クズ", "デコスケ"
    .secretName = "ち~んw"    '……(1)'
    Debug.Print .secretName    '……(2)'
    .Show
  End With
End Sub

追加したのは2箇所。

(1)の

.secretName = "ち~んw"

でUserFormTemplateのインスタンスのsecretNameプロパティに値「ち~んw」を設定。

(2)の

Debug.Print .secretName

でsecretNameプロパティの値をイミディエイト・ウインドウに出力する。

実行結果

f:id:akashi_keirin:20170918213028j:plain

ユーザーフォームが表示されて、

f:id:akashi_keirin:20170918230445j:plain

イミディエイトにはsecretNameプロパティの値が表示された。

フィールドやプロパティまで持たせられるなんて、ますますクラスモジュールとの区別が分からなくなってきたなあ。いや、分かるけどw

@akashi_keirin on Twitter

ユーザーフォームをクラスっぽく使おう!

ユーザーフォームをクラスっぽく使う

ユーザーフォームのテンプレート(?)

前回の

akashi-keirin.hatenablog.com

で、ユーザーフォームもNewできると分かった。

で、それが何の役に立つのか、イマイチよく分からないんだが、

よく使うパターンのユーザーフォームのひな形を作っておいて、部分的に柔軟性を持たせたらいいんでね?

と思ったので、実験してみた。

ユーザーフォームのひな形を作る

手の込んだものを作るのはメンドクサイので、次のようなものにした。

f:id:akashi_keirin:20170918212932j:plain

オブジェクト名は「UserFormTemplate」とした。

見ての通り、コマンドボタンを3つ設置。

オブジェクト名は、左から順に

f:id:akashi_keirin:20170918212946j:plain

「BtnLeft」。

f:id:akashi_keirin:20170918213006j:plain

「BtnCenter」。

f:id:akashi_keirin:20170918213017j:plain

「BtnRight」。

今まで、ユーザーフォーム上のコントロールのオブジェクト名は「lblPersonName」みたいにキャメル記法を使っていたんだけど、"オブジェクト名"ってことはクラス名みたいなもんだから、パスカル記法の方が良いと思い直した。

んで、UserFormTemplateのモジュールに、次のコードを書いた。

リスト1 フォームモジュール
Public Sub init(ByVal formCaption As String, _
                ByVal btnLeftName As String, _
                ByVal btnCenterName As String, _
                ByVal btnRightName As String)
  With Me
    .Caption = formCaption    '……(*)'
    .BtnLeft.Caption = btnLeftName
    .BtnCenter.Caption = btnCenterName
    .BtnRight.Caption = btnRightName
  End With
End Sub

おなじみ、擬似コンストラクタのinitメソッド。

ユーザーフォームの_Initializeメソッドも引数を持たせられないから、仕方なくこうした。

(*)からの4行

.Caption = formCaption
.BtnLeft.Caption = btnLeftName
.BtnCenter.Caption = btnCenterName
.BtnRight.Caption = btnRightName

は、いづれもMe、すなわちUserFormTemplateのインスタンスに対する処理。

それぞれ、ユーザーフォーム、左ボタン、中央ボタン、右ボタンのキャプションに引数で渡された文字列をセットする。

Newしてインスタンス化した後は、必ずこのinitメソッドを呼ぶ、という約束にする。

んで、このユーザーフォームを使うコードを標準モジュールに書く。

スト2 標準モジュール
Public Sub userFormTest()
  Dim uFrm As UserFormTemplate    '……(1)'
  Set uFrm = New UserFormTemplate    '……(2)'
  With uFrm
    .init "アホ", "ボケ", "クズ", "デコスケ"    '……(3)'
    .Show    '……(4)'
  End With
End Sub

(1)の

Dim uFrm As UserFormTemplate

で、UserFormTemplate型の変数uFrmを宣言。

(2)の

Set uFrm = New UserFormTemplate

でUserFormTemplateをインスタンス化。クラスモジュールの使い方と同じ。

(3)の

.init "アホ", "ボケ", "クズ", "デコスケ"

は、uFrmの擬似コンストラクタinitメソッドを、4つの引数を渡して実行。4つの引数は、前から順に、それぞれフォーム、左ボタン、中央ボタン、右ボタンのキャプションとなる。

initメソッドで初期化をしたら、あとは(4)の

.Show

でフォームを表示しておしまい。

実行。

f:id:akashi_keirin:20170918213028j:plain

ちゃんとそれぞれキャプションが設定された状態で表示された。

最後に

ユーザーフォームを用いたアプリで、似たようなフォームを多用するようなやつを作成するときになら、少しは役に立つかも知れんなあ。

前に予定管理アプリみたいなのを自作した(させられた)ときにこの知識があったら、もう少しラクできていたかも。

akashi-keirin.hatenablog.com

@akashi_keirin on Twitter

ユーザーフォームはNewできるか

ユーザーフォームをNewしてみる

ユーザーフォームって、クラスモジュールに似てね?

クラスモジュールを使っていなかった頃はなんとも思ってなかったが、クラスモジュールをよく使うようになって、改めてユーザーフォームを使ってみると、結構共通点があったんだなあ、と。

「オブジェクト名」というパラメータがあったり、「~~_Initialize」というのがあったり。

……ということは、

Newして変数やら配列やらにぶち込むこともできるんじゃね?

と思ったわけです。

で、やってみた。

まずは、

f:id:akashi_keirin:20170918093649j:plain

このようなユーザーフォームを挿入。

ほぼデフォルトの状態。タテ幅を小さくしただけ。

f:id:akashi_keirin:20170918093658j:plain

コントロールはラベルだけにしとく。

こちらもほぼデフォルトの状態。フォントサイズを大きくしてテキストを中央寄せにしただけ。

フォームモジュールには、とりあえずコンストラクタだけを設定しておく。

リスト1 フォームモジュール
Option Explicit

Private Sub UserForm_Initialize()
  Me.Show vbModeless    '……(*)'
End Sub

計算通りなら、インスタンス化されるとすぐにユーザーフォームが表示されるはず。

デフォルトだと、ユーザーフォームを閉じないと次の処理に進まないので、Modelessで表示することにしとく。

標準モジュールには次のコードを書く。

スト2 標準モジュール
Public Sub test()
  Dim objForm(0 To 4) As UserForm    '……(1)'
  Dim i As Integer
  For i = 0 To 4
    Set objForm(i) = New UserForm1    '……(2)'
    objForm(i).Label1.Caption = "アホ" & _
	                            StrConv(i + 1, vbWide) & "号"    '……(3)'
  Next
End Sub

(1)の

Dim objForm(0 To 4) As UserForm

では、UserForm型の要素数5の配列を準備。

コード入力中は、

f:id:akashi_keirin:20170918093716j:plain

ちゃんとインテリセンスがきく。安心。

んで、(2)の

Set objForm(i) = New UserForm1

で、UserForm1をインスタンス化し、配列にぶち込む。

これが実行された段階で、リスト1の(*)が実行されるので、ユーザーフォームがModeless表示されるはず。

んで、その後(3)の

    objForm(i).Label1.Caption = "アホ" & _
	                            StrConv(i + 1, vbWide) & "号"

で、ラベルのCaptionプロパティに文字列「アホ○号」を設定しておしまい。

コード入力中は、

f:id:akashi_keirin:20170918093724j:plain

インテリセンスが働かない。不安。

【追記】

変数「objForm()」を「UserForm1型」で宣言していれば、ちゃんとインテリセンスが働きます。単なる私のコーディングミスです。すんまへん。

====追記ここまで====

いざ、実行

f:id:akashi_keirin:20170918093736j:plain

こんな感じ。ちょっと周辺の影が濃い……?

めくっていくと、

f:id:akashi_keirin:20170918093817j:plain

ちゃんと5つのフォームが表示されている。

おわりに

ユーザーフォームもNewできるし、変数や配列にぶち込むこともできます。

しかしながら、これが何の役に立つのか、サッパリ分かりまへん。

@akashi_keirin on Twitter

素人がアドインの世界に首を突っ込んでみる

素人、アドインに手を出す

アドインとは……?

「アドイン」って、よく聞く言葉だったけど、意味が分からんかったのでずっと放置していた。

何かの拍子に「マクロをアドインとしてうんたらかんたら」というのを読んで、ちょっと調べてみた。

そしたらアンタ、こういうのが見つかったのですよ。

作成したマクロを他のどのブックでも使用できるようにする方法です。アドインとして保存すると便利です。

何ーーーーッ! マジか!!!!!!!!

し、知らんかった……。

ということは、ですよ、

しちめんどくさい操作をアドインとして登録しておいて、クイックアクセスツールバーなんかにボタンを設置しておいたらメッチャ楽

つうことですよね?

何ということだ……。そんなこと知らんかったから、今までめんどくさい文字列処理なんかは、それ専用のマクロ入りブックを立ち上げていたんだけど……。

なんちゅうムダなことをやってたんだw

マクロのアドイン化に挑戦

というわけで、やってみた。

サンプルコードは次のリスト1を使う。

リスト1 標準モジュール
Option Explicit

Public Sub convertToNarrowWhenAlphaNumeric()
  Dim objCell As Range
  For Each objCell In Selection
    objCell.Value = checkAndConvert(objCell.Value)
  Next
End Sub

Private Function checkAndConvert( _
                   ByVal tgtString As String) As String
  Dim i As Integer
  Dim str As String
  Dim chr As String
  Dim tmp As String
  str = StrConv(tgtString, vbWide)
  tmp = ""
  For i = 1 To Len(str)
    chr = Mid(str, i, 1)
    If chr Like "[0-9]" Or _
       chr Like "[A-z]" Or _
       chr = "-" Or _
       chr = "&" Then chr = StrConv(chr, vbNarrow)
    tmp = tmp & chr
  Next
  checkAndConvert = tmp
End Function

今回はコードの説明は省略。リクエストがあったらやりますのでヨロシク。

選択範囲のセルの文字列について、英数字及び「-」(ハイフン)、「&」(アンパサンド)については半角に統一する、というマクロですな。

コイツをアドインとして登録し、いつでも使えるようにしようという算段。

手順

まずは、上記のコードを標準モジュールに書く。

んで、「名前を付けて保存」ダイアログ・ボックスを呼び出し、

「ファイルの種類(T)」を「Excelアドイン(*.xlam)」にして保存

する。

f:id:akashi_keirin:20170917102713j:plain

保存場所は、自動的に

C:\Users>ユーザー名>AppData>Roaming>Microsoft>AddInsフォルダ

が選ばれる。

ファイル名は日本語にしておくのが分かりやすいかな。画像では「英数記号半角統一」にしてあります。

これでExcel本体への登録はおk。不安になるぐらい簡単です。

お次は、登録したアドインを使えるようにする。

f:id:akashi_keirin:20170917102720j:plain

「ファイル」タブから、

f:id:akashi_keirin:20170917102735j:plain

「オプション」→

f:id:akashi_keirin:20170917102748j:plain

「アドイン」へと進む。

f:id:akashi_keirin:20170917102757j:plain

下の方に「管理(A)」というところがあるので、ドロップダウンリストから「Excelアドイン」を選んで「設定」をクリック。

f:id:akashi_keirin:20170917102810j:plain

アドインというウインドウが出てくるので、先ほど保存した「英数記号半角統一」にチェックを入れて
f:id:akashi_keirin:20170917102824j:plain

[OK]をクリック。これで使用準備は完了。

あとは、呼び出し方を設定するだけ。

今回は、クイックアクセスツールバーから呼び出すことにする。

f:id:akashi_keirin:20170917102832j:plain

「ファイル」タブをクリック→「オプション」へと進む。

f:id:akashi_keirin:20170917102845j:plain

「クイックアクセスツールバー」をクリック。

f:id:akashi_keirin:20170917102903j:plain

右側の画面にこんなのが出てくるので、「コマンドの選択」ドロップダウンリストから「マクロ」を選ぶ。

f:id:akashi_keirin:20170917102913j:plain

下段のボックスの中に、マクロ名が表示されるので、(今回の例の場合なら)「英数記号半角.xlam」に書かれている方のプロシージャ名を選択し(マウスポインタを当てると、ファイルフルパスがヒントで表示されるので見分けられる)、

f:id:akashi_keirin:20170917102923j:plain

[追加]ボタンをクリック。

f:id:akashi_keirin:20170917102942j:plain

右側のボックスに追加されている。

「アイコン、だっせぇよな!」と思ったら、

f:id:akashi_keirin:20170917102953j:plain

下の方にある[変更]ボタンをクリックすると、

f:id:akashi_keirin:20170917103029j:plain

「ボタンの変更」ウインドウが表示されるので、カッコいいアイコンに変更すればおk。

f:id:akashi_keirin:20170917103043j:plain

アイコンがカッコよくなった。

元の画面に帰ると、

f:id:akashi_keirin:20170917103104j:plain

クイックアクセスツールバーにカッコいいアイコンがw

これで準備おkです。

いざ実行。

f:id:akashi_keirin:20170917103453j:plain

対象のセル範囲(よく見ないと分からないかも知れませんが、英数記号部分は全角・半角がチャンポンになっていて、かなりイラッと来るものとなっています)を選択して、

f:id:akashi_keirin:20170917103510j:plain

カッコいいアイコンwをクリック!

f:id:akashi_keirin:20170917103525j:plain

英数記号が半角で統一されました。

おわりに

今回例として使用した「英数記号全角半角統一」マクロは、コチラの『実例で学ぶExcelVBA(講談社ブルーバックス B1802 立山秀利著)』がもとになっています。私がVBAに目覚めるきっかけとなった、大変ありがたい本です。密林での評価は前作の『入門者のExcelVBA(講談社ブルーバックス B1769 著者同じ)』の方が高いようですけど、どう考えても『実例で~』の方が上だと思っています。

手数の多い文字列処理なんかは、マクロで作っておいてアドインにすると便利かも。特に、いろんなところから集まってくるExcelブックを集約するような仕事のときには、こういうデータクレンジング系のマクロをアドインとして放り込んでおくと楽になるでしょうね。

@akashi_keirin on Twitter

WorkbooksコレクションのAddメソッドに自分自身のフルパスを渡すとExcelが落ちる

Excelが落ちる

WorkbooksコレクションのAddメソッド

akashi-keirin.hatenablog.com

に、ExcelVBAer(id:x1xy2xyz3) さんから、次のようなコメントをいただいた。

参考までに、WorkBooks.Add([originalFileFullName]) という方法も知っておくといいかもね~

Addメソッドの引数に、元のファイルのフルパスを指定して実行するという意味だと思うのだけれど、どんな結果になるのか想像もつかなかった。

で、やってみた

とりあえず、次のようなコードを書いてみた。

リスト1
Public Sub testAddMyself()
  Dim originalWorkbook As Workbook
  Set originalWorkbook = ThisWorkbook
  Dim newWorkbook As Workbook
  Set newWorkbook = Workbooks.Add(originalWorkbook.FullName)
End Sub

んで、実行してみた。

f:id:akashi_keirin:20170827173532j:plain

……。

元のブックは「親ブック.xlsm」というファイル名なのだけれど、新しくできたブックは「親ブック1」という名前になっているみたい。

全く同じファイルパスなんだから、新しい方に「1」を付けたんだろうけど、次の瞬間にExcelが落ちる。

 

これは何回やっても同じだった。

まあ、そもそも ExcelVBAer(id:x1xy2xyz3) さんのコメントを理解できていないということなのでしょう。

おわりに

こんなしょうもない記事が通算100記事目だなんて……。

@akashi_keirin on Twitter

列番号を列符号に変換する関数

列符号を割り出す関数を作る

Split関数の挙動

セルのAddressプロパティを取得すると、例えばA1セルなら、「$A$1」という文字列が返る。

ということは、「$」をデリミタとしてSplit関数を使えば、列符号を表す「A」がSplit関数の返り値である配列のどこかに格納されるはずだ。

で、やってみた。

リスト1
Public Sub testSplitFunction()
  Dim arraySample As Variant
  arraySample = Split("$A$1", "$")    '……(1)'
  Dim i As Integer
  For i = 0 To UBound(arraySample)
    Debug.Print i & " : "; arraySample(i)
  Next
End Sub

(1)の

arraySample = Split("$A$1", "$")

では、Split関数を使って文字列「$A$1」を区切り文字(デリミタ)「$」で区切った結果を配列にして変数arraySampleにぶち込んでいる。

元の文字列がデリミタである「$」で始まっているこんなとき、返り値である配列はどうなるか。

f:id:akashi_keirin:20170827171408j:plain

こうなる。

配列の1つ目の要素(インデックス番号「0」)は「""」になるようだ。

したがって、Split関数の引数にセルのAddressプロパティを渡して、出来た配列の2番目の要素(インデックス番号「1」)が列符号を表す文字列になると分かる。

列番号を渡したら列符号を返す関数

作ってみた。

スト2
Public Function getColumnLetter(ByVal columnNumber As Long) As String
On Error GoTo errorHandler
  Dim Sh As Worksheet    '……(1)'
  Set Sh = ActiveSheet
  Dim tmpStr As String
  tmpStr = Sh.Cells(1, columnNumber).Address    '……(2)'
  Dim tmpArray As Variant
  tmpArray = Split(tmpStr, "$")   '……(3)'
  getColumnLetter = tmpArray(1)    '……(4)'
  Exit Function
errorHandler:
  getColumnLetter = ""
End Function

(1)からの2行、

Dim Sh As Worksheet
Set Sh = ActiveSheet

は別になくてもいいんですが、裸で「Range(……)」とか、「Cells(……)」とか書くのがイヤだからこうしているだけです。

まあ、「そんなこと言うならApplicationオブジェクトから書けや!」とか言われるかも知れませんが。

(2)の

tmpStr = Sh.Cells(1, columnNumber).Address

では、引数で渡された列番号に相当する列の1行目のAddressプロパティの文字列を変数tmpStrにぶち込んでいる。

まあ、直接Split関数に渡してもいいんだが、可読性のためにこうしている。

(3)の

tmpArray = Split(tmpStr, "$")

で変数tmpArrayの2番目の要素、すなわち「tmpArray(1)」には列符号を表す文字列が入っているはずなので、

(4)の

getColumnLetter = tmpArray(1)

でtmpArray(1)を返り値にしてやる。

動作テスト

次のコードで実験。

Public Sub test()
  Debug.Print getColumnLetter(10000)
End Sub

10000列目の符号をイミディエイト・ウインドウに表示するというだけ。

f:id:akashi_keirin:20170827171419j:plain

ほれ、この通り、「NTP」と表示されている(核不拡散条約かよwww←「NPT」な。)。

下の2行を見てもらったら、NTP列が10000列目であることも確認していただけよう。

おわりに

まあ、何に使うのかはよく分かりません。

@akashi_keirin on Twitter

親ブックから子ブックを量産する

データを変えて親ブックから子ブックを量産するマクロ

子ブック生成部分を切り出す

akashi-keirin.hatenablog.com

の続き。

FileSystemObjectオブジェクトのCopyFileメソッドを使うと、子ブックの生成が簡単にできることが分かったので、いよいよ量産体制に入る。

そのために、子ブック生成部分だけを切り出しておこう。

リスト1
Private Function saveNewWorkbook(ByVal originalFileFullName As String, _
                                 ByVal newFileFullName As String) As Workbook
  Dim fsObject As FileSystemObject    '……(1)'
  Set fsObject = New FileSystemObject
  fsObject.CopyFile Source:=originalFileFullName, _
                    Destination:=newFileFullName
  Set saveNewWorkbook = Workbooks.Open(newFileFullName)    '……(2)'
  Set fsObject = Nothing
End Function

見ての通り、引数を2つ受け取って、新たに生成して保存した子ブックを開いて返すメソッドにした。呼び出され専用なのでPrivateにしている。

まず、(1)からの3行

Dim fsObject As FileSystemObject
Set fsObject = New FileSystemObject
fsObject.CopyFile Source:=originalFileFullName, _
                  Destination:=newFileFullName

は、FileSystemObjectオブジェクトのインスタンスを生成して、CopyFileメソッドを用いる。

これで新しい子ブックが保存される。

次に(2)の

Set saveNewWorkbook = Workbooks.Open(newFileFullName)

では、早速保存した新しい子ブックを開いて返り値にしている。

新しく生成された子ブックに加工したいということが多いと思うので、保存しっぱなしではなく、一旦開いて返り値とするというやり方にした。

第2引数のnewFileFullNameをOpenメソッドの引数にそのまま使えるので楽。

子ブックを量産する

あとは、

  • 親ブックの「個別」シートに「元データ」シートからデータ(笑)を転記する。
  • 一旦親ブックを保存する。
  • 別フォルダにコピーを作成し、子ブックとする。
  • 子ブックを加工する。
  • 子ブックを保存して閉じる。

という処理をForループで回したらよい。

コーディング

スト2
Public Sub main()
  Dim originalWorkbook As Workbook
  Set originalWorkbook = ThisWorkbook
  Dim folderPath As String
  folderPath = originalWorkbook.Path & "\収容所\"  '"
  If Dir(folderPath, vbDirectory) = "" Then MkDir (folderPath)
  Dim orgDataSh As Worksheet
  Set orgDataSh = originalWorkbook.Worksheets("元データ")
  Dim tgtSh As Worksheet
  Set tgtSh = originalWorkbook.Worksheets("個別")
  Dim maxRow As Long
  maxRow = orgDataSh.Cells(Rows.Count, 2).End(xlUp).Row
  Dim newWorkbook As Workbook
  Dim i As Long
  For i = 2 To maxRow
    tgtSh.Range("A1").Value = orgDataSh.Range("B" & i).Value    '……(1)'
    Application.DisplayAlerts = False    '……(2)'
    originalWorkbook.Save    '……(3)'
    Set newWorkbook = saveNewWorkbook(originalWorkbook.FullName, _
                                      folderPath & "子ブック" & Format(i - 1, "0#") & ".xlsm")    '……(4)'
    newWorkbook.Worksheets("元データ").Delete    '……(5)'
    newWorkbook.Close True    '……(6)'
    Application.DisplayAlerts = True    '……(7)'
  Next
  Set originalWorkbook = Nothing
  Set orgDataSh = Nothing
  Set tgtSh = Nothing
  Set newWorkbook = Nothing
End Sub

Forループに入るまでの処理については、説明を省略。オーソドックスな処理ばかりだと思う。

で、Forループの中身だが、

まず(1)の

tgtSh.Range("A1").Value = orgDataSh.Range("B" & i).Value

で、親ブックの「元データ」シートから親ブックの「個別」シートにデータ(笑)を転記。

(2)の

Application.DisplayAlerts = False

でアラート表示を止める。これをやっておかないと、次の処理のときにアラート表示が出てしまう。

(3)の

originalWorkbook.Save

で親ブックを保存。こうしておかないと、データ(笑)の転記が子ブックに反映されない。

ここまで下ごしらえをしておいて、いよいよ(4)の

Set newWorkbook = saveNewWorkbook(originalWorkbook.FullName, _
                                  folderPath & "子ブック" & Format(i - 1, "0#") & ".xlsm")

で子ブックを保存した上で開き、変数newWorkbookに格納。

(5)の

newWorkbook.Worksheets("元データ").Delete

で子ブックの「元データ」シートを削除し、

(6)の

newWorkbook.Close True

で、子ブックを保存して閉じる。

最後に(7)の

Application.DisplayAlerts = True

でアラート表示を元に戻したら、オブジェクト変数を解放して終了。

実行

mainプロシージャを実行すると、

f:id:akashi_keirin:20170812165846j:plain

「収容所」フォルダにちゃんと5つのファイルができている。

f:id:akashi_keirin:20170812165856j:plain

それぞれ「個別」シートのA1セルにデータ(笑)も転記されている。

おわりに

さっそく、

akashi-keirin.hatenablog.com

このとき作ったクラスを修正しようかなあ。

ただ、子ブックもマクロ付きのままってのはちょっと具合が悪いんだよなあ。

@akashi_keirin on Twitter