• ベストアンサー

VBA 簡潔なコードを書くために

現在、下記のようなコード書いて利用しています。 このコードを他の人がに転用する時に、指定箇所さえ書き換えれば簡単に転用できる!と言うようにしたいのです。 例えば >Set myBook = Workbooks.Open(Filename:=myDir & "\" & myName) >Set Copydata = SH1.Range("Z1").Resize(100, 1) といった指定するような箇所(" "で囲った所)を先にまとめて定義しておくにはどう記述したらよいのでしょうか。 宜しくお願いします。 ------------------------------------------------------------- Private Sub 読込ボタン_Click() '他のBookからデータを転記するマクロ Dim SH2 As Worksheet, SH1 As Worksheet Dim GYO As Range, Copydata As Range Dim myDir As String, myName As String, myBook As Workbook Set SH2 = ThisWorkbook.Worksheets("情報シート") '集計用のBookがあるフォルダ名を指定(このBookを格納している場所) myDir = ThisWorkbook.Path '他Bookのファイル名を指定(*.xls) myName = Dir(myDir & "\" & "*.xls") Do While myName <> "" 'このBook以外を対象 If myName <> ThisWorkbook.Name Then '転記先[情報シート]の最終行を取得 Set GYO = SH2.Range("A65536").End(xlUp).Offset(1) '他のBookを開いて変数に格納 Set myBook = Workbooks.Open(Filename:=myDir & "\" & myName) '転記元を取得(Z列1行を基点に100行コピー) Set SH1 = myBook.Worksheets("回答内容") Set Copydata = SH1.Range("Z1").Resize(100, 1) '転記先の最終次行に転記(行列入替で貼付) Copydata.Copy GYO.PasteSpecial Paste:=xlPasteValues, Transpose:=True '開いた他Bookを閉じる myBook.Close End If myName = Dir() Loop End Sub -------------------------------------------------------------

質問者が選んだベストアンサー

  • ベストアンサー
  • hige_082
  • ベストアンサー率50% (379/747)
回答No.5

>このコードを他の人がに転用する時に、指定箇所さえ書き換えれば簡単に転用できる! 汎用性を持たせたいと言うことかな Private Sub 読込ボタン_Click() '他のBookからデータを転記するマクロ Dim SH2 As Worksheet, SH1 As Worksheet Dim GYO As Range, Copydata As Range Dim myDir As String, myName As String Dim myBook As Workbook Dim SH2_Name As String, SH1_Name As String Dim Copydata_Home As String '設定開始--------------------------------------- SH2_Name = "情報シート" '転記先シート名 SH1_Name = "回答内容" '転記元シート名 Copydata_Home = "Z1" '転記元の基点(セル)を指定 '設定終了--------------------------------------- Set SH2 = ThisWorkbook.Worksheets(SH2_Name) '集計用のBookがあるフォルダ名を指定(このBookを格納している場所) myDir = ThisWorkbook.Path '他Bookのファイル名を指定(*.xls) myName = Dir(myDir & "\" & "*.xls") Do While myName <> "" 'このBook以外を対象 If myName <> ThisWorkbook.Name Then '転記先[情報シート]の最終行を取得 Set GYO = SH2.Range("A65536").End(xlUp).Offset(1) '他のBookを開いて変数に格納 Set myBook = Workbooks.Open(Filename:=myDir & "\" & myName) '転記元を取得(Z列1行を基点に100行コピー) Set SH1 = myBook.Worksheets(SH1_Name) Set Copydata = SH1.Range(Copydata_Home).Resize(100, 1) '転記先の最終次行に転記(行列入替で貼付) Copydata.Copy GYO.PasteSpecial Paste:=xlPasteValues, Transpose:=True '開いた他Bookを閉じる myBook.Close End If myName = Dir() Loop End Sub 設定開始~設定終了の間の3行を設定すれば、後は変更することなく マクロを実行できますで良いのかな?

004532
質問者

お礼

こんな感じのイメージでした。 ありがとうございます。 "設定"する場所を頭にもってきて、まとめて定義しておきたかったです。

その他の回答 (5)

  • end-u
  • ベストアンサー率79% (496/625)
回答No.6

コード内で設定せずに、InputBoxを使って対話式にしたりとか、 Sub 例えば()   With Sheets.Add     .Name = "config"     .Range("A1:B1").Value = [{"フォルダ選択?(しない場合はこのBookのフォルダ)","yes"}]     .Range("A2:B2").Value = [{"転記先シート名?","情報シート"}]     .Range("A3:B3").Value = [{"転記元シート名?","回答内容"}]     .Range("A4:B4").Value = [{"転記元のセル?","Z1"}]   End With End Sub こんな「設定用シート」みたいな感じで外に出して、このシートを修正してもらい、 VBAからはその「設定用シート」の値を変数に取り込んで実行したりとか、も、考えられますね。 Option Explicit Sub test()   Dim SH   As Worksheet   Dim SH1   As Worksheet   Dim SH2   As Worksheet   Dim GYO   As Range   Dim myDir  As String   Dim myName As String   Dim shtName As String   Dim kiten  As String   With ThisWorkbook     On Error GoTo errHndr     Set SH = .Sheets("config")     Set SH2 = .Sheets(SH.Range("B2").Value)     On Error GoTo 0     shtName = SH.Range("B3").Value     kiten = SH.Range("B4").Value     If SH.Range("B1").Value = "yes" Then       myDir = FDSELECT     Else       myDir = .Path     End If   End With   If Len(myDir) = 0& Then Exit Sub   Application.ScreenUpdating = False   myName = Dir(myDir & "\" & "*.xls")   Do While myName <> ""     'このBook以外を対象     If myName <> ThisWorkbook.Name Then       '転記先シートの最終行を取得       Set GYO = SH2.Range("A65536").End(xlUp).Offset(1)       '他のBookを開く       With Workbooks.Open(Filename:=myDir & "\" & myName, ReadOnly:=True)         On Error Resume Next         Set SH1 = .Worksheets(shtName)         On Error GoTo 0         If Not SH1 Is Nothing Then           '転記元を取得(?列1行を基点に100行コピー)           SH1.Range(kiten).Resize(100).Copy           '転記先の最終次行に転記(行列入替で貼付)           GYO.PasteSpecial Paste:=xlPasteValues, Transpose:=True           Application.CutCopyMode = False           Set SH1 = Nothing         End If         '開いた他Bookを閉じる         .Close False       End With     End If     myName = Dir()   Loop errHndr:   Application.ScreenUpdating = True   If Err.Number <> 0 Then MsgBox "設定シートがありません。処理中止"   Set GYO = Nothing   Set SH = Nothing   Set SH2 = Nothing End Sub '--------------------------------------------------------------------- Private Function FDSELECT() As String 'フォルダ選択Function   Dim obj As Object   Dim ret As String   Set obj = CreateObject("Shell.Application") _        .BrowseForFolder(0, "SelectFolder", 0)   If obj Is Nothing Then Exit Function   On Error Resume Next   ret = obj.self.Path & "\"   If Err.Number <> 0 Then     ret = obj.Items.Item.Path & "\"     Err.Clear   End If   On Error GoTo 0   Set obj = Nothing   FDSELECT = ret End Function

004532
質問者

お礼

かなりプロフェッショナルなコードですね。 アドバイスありがとうございます。 試してみます!

回答No.4

関数(手続きだけど)の例 Private Sub 読込ボタン_Click() LoadingHandler(myDir & "\" & myName,"Z1") End Sub Sub LoadingHandler( AFileName As String _ ,ARange As String) 省略 Set myBook = Workbooks.Open(Filename:=AFileName) Set Copydata = SH1.Range(ARange).Resize(100, 1) 省略 End Sub クラスは、さっきのURLの2ページ目に書き方が簡潔に書いてありますので補足しません。

004532
質問者

お礼

さらに具体的にご説明いただきありがとうございます!

回答No.3

なるほど。 ・パラメータを与えるだけで動くような関数を作成するとか。 ・クラスにしてしまうとか。 参考: https://codezine.jp/article/detail/499 クラスにしてしまえば、表面のコードは、かなりシンプルになると思います。 クラスを作成するに当たって、手っ取り早いのは、最初にプロパティやメソッドなどの一覧をつくってしまいます。 で、あとから1つずつ、実装していけばよいです。

004532
質問者

お礼

ありがとうございます。 始めにまとめて一覧を作っておけば、他に転用するときも、一覧の箇所のみ変更すれば良いのですね!

  • WDY
  • ベストアンサー率27% (121/433)
回答No.2

こんにちわ どういう書き方がいい書き方かというのは分かりませんが 私がよく行う方法は '---------○○○○○○○の設定----------------- '---------○○○○○○○の設定ココまで----------------- の様にブロック化してしまいます。 沢山コメントがあれば後で読んだ時に自分も分かるし 自分以外の人が修正する場合も分かりやすいと思います。

004532
質問者

お礼

アドバイスありがとうございます。 書き方が悪かったかもしれませんが、コードとしてスリム化したかったので、補足説明の「'~の」では目的が違ってしまいます…スミマセン

回答No.1

Const a=1 Const b="string" で、それを使う場所で a とか b を参照するようにすれば、よろしいかと。

004532
質問者

お礼

有難うございました。

004532
質問者

補足

アドバイスありがとうございます! Constを使ってスリム化しようと考えていました。 が、上手くいきません。CopydataはmyBookの中のSH1に存在するので、リンクだらけでどうConstを使って良いか困っています。 宜しければ具体的にアドバイスいただけると大変助かります。 >'他のBookを開いて変数に格納 >Set myBook = Workbooks.Open(Filename:=myDir & "\" & myName) >'転記元を取得(Z列1行を基点に100行コピー) >Set SH1 = myBook.Worksheets("回答内容") >Set Copydata = SH1.Range("Z1").Resize(100, 1)

関連するQ&A

  • VBA 開いているブックの場所

    ExcelでVBAを利用して、フォルダ(c:\"VBA練習")に置いてあるExcleの内容を、開いているExcleに自動読取り作業をするために、下記のようなコードを記述しました。(正常に動作します) そこで、ご相談なのですが、現在は特定のフォルダ(c:\"VBA練習")にExcelを置かないと読み取りは実現しません。ですが、開いているBookが置いてある"場所"にあるExcelを読み取りたい場合、どのように書き換えれば宜しいでしょうか? ご教授いただけると助かります。宜しくお願いします。 -------------------------------------------------------------- Private Sub 読込ボタン_Click() Dim myDir As String, myName As String, myBook As Workbook Dim copydata As Range, GYO As Range Dim SH2 As Worksheet, SH1 As Worksheet Set SH2 = ThisWorkbook.Worksheets("情報シート") '集計用のブックがあるフォルダ名を指定 myDir = "C:\VBA練習" myName = Dir(myDir & "\" & "*.xls") Do While myName <> "" Set GYO = SH2.Range("A65536").End(xlUp).Offset(1) '(1)指定した名前のブックを開いて変数に格納する Set myBook = Workbooks.Open(Filename:=myDir & "\" & myName) '(2)転記元を取得する Set SH1 = myBook.Worksheets("回答内容") Set copydata = SH1.Range("Z1").Resize(100, 1) '(3)転記先に貼り付ける copydata.Copy GYO.PasteSpecial Paste:=xlPasteValues, Transpose:=True '(4)開いたブックを閉じる myBook.Close myName = Dir() Loop End Sub --------------------------------------------------------------

  • 複数のブックからデータを転記するマクロについて

    こんにちは。 VBAの素人なのでネットや本などで自分なりに調べましたが、 どうにも解決できないので、ご教示いただけませんでしょうか。 複数のブックにある同一セル番地にある データを別のブックにまとめたいのですが、 ブック数が500程度あり、マクロでうまくできないか悩んでいます。  (1)転記元ブックを開く。  (2)転記元データをコピーする。  (3)転記先ファイルのセルに貼り付ける。  (4)転記元ブックを閉じる。 の繰り返しだと思うのですが、(2)ができず困っています。 ちなみに、500のブックとまとめるブックも同じフォルダにあります。 具体的には、転記元ブックは以下のような形で、A列に様々な温度のデータが縦に並んでいます。    A列   1行  温度  2行  27 ←ここのみ抽出したい 3行  28 4行  30 それぞれのブックのA2番地の温度データのみを抽出し、転記先ブックのA2からA500までまとめたい。 組んだマクロは以下です。 ------------------------------ Sub 特定フォルダ内ブックを並べ替えて転記() Dim myDir As String, myName As String, myBook As Workbook Dim motodata As Range, sakidata As Range   '集計用のブックがあるフォルダ名を指定 myDir = "D:\VBA練習" myName = Dir(myDir & "\" & "*.xls")   Do While myName <> ""   '↓転記先の最新レコード位置を取得する   Set sakidata = Range("A65536").End(xlUp).Offset(1)   '↓(1)指定した名前のブックを開いて変数に格納する  Set myBook = Workbooks.Open(Filename:=myDir & "\" & myName)   '↓(2)転記元を取得する   Set motodata = myBook.Range("A2")      '↓(3)転記先に貼り付ける   motodata.Copy sakidata   '↓(4)開いたブックを閉じる   myBook.Close  myName = Dir()  Loop End Sub ------------------------------ mybookというキーワードを使用して、A2セルデータをコピーする構文をご教示いただけませんでしょうか。 以上、長々となってしまいましたが、何卒アドバイスの程お願いいたします。

  • VBA 別シートの最終行に追記

    ExcelのSheet1で作成した表の一部項目を、Sheet2に一覧表としてまとめたいのです。 例えばSheet1にアンケート項目のような入力されていて、毎日使いまわします。 セルA1: 訪問日→固定     セルB1: (日付)→更新 セルA3: お客様指名→固定  セルB3: (氏名)→更新 使いまわすので、1度入力されたものは、Sheet2に一覧表として転記しておきたいのです。Sheet2の一覧表の最終行をみつけて追記していきたいです。 書いてみたのは以下の通り。 Private Sub 登録ボタン_Click() Dim SH1 As Worksheet, SH2 As Worksheet Dim GYO As Long Set SH1 = ThisWorkbook.Worksheets("回答内容") Set SH2 = ThisWorkbook.Worksheets("情報シート") ' Sheet2の最終行を取得 GYO = SH2.Range("$A$65536").End(xlUp).Row ' 最終行の次行を取得 If SH2.Cells(GYO, 1).Value <> "" Then GYO = GYO + 1  ' 現在の収容位置の下に転記 SH2.Cells(GYO, 1).Resize(1, 20).Value = SH1.Range("$c$2:$D$10").Value With SH1 .Range("A3").Copy Destination:=SH2.Range("A2") .Range("B3").Copy Destination:=SH2.Range("B2") End With End Sub 項目は飛び飛びのセルに入力されていて、それらをまとめて一覧表の1行にまとめたいと思っています。 ここでは例としてSheet1[A3][B3]セルをSheet2へ転記していますが、項目はもっといっぱいあります。 記載したコードで実行すると、1回目は転記されますが、2回目以降が追記されていきません。 ' 現在の収容位置の下に転記 のところに問題があると思っています。 全くの初心者が、コードを書くのには無理があると思いますが、どなたか教えていただけないでしょうか。宜しくお願いします。

  • ExcelVBAでの転記処理エラーについて

    ExcelVBAを使用して、データを転記集約させる作業をしたいと思っています。 詳しく言いますと、同一のフォルダ内に各店からの注文書のファイルを保存し(フォーマットは同じ)、それを集計用のファイルで、それぞれ入力してあるデータを読み込み一覧にしていくという作業です。 転記部分をサブルーチンにしています。 実行すると、最後の topRng.PasteSpecial xlPasteValues でエラーになり、「実行時エラー1004 この操作には同じサイズの結合セルが 必要です」とメッセージが出ます。 そこで結合セルを解除したのですが、同じメッセージが出てしまいます。 どこをどう修正すればよいのか、お教え頂けないでしょうか? 転記先のセルの開始位置の取得が間違っているのでしょうか? 宜しくお願いいたします。 Dim keyRng As Range Sub 集計開始() myDir = "D:\集計用" flg = 0 ChDir myDir MyName = Dir(myDir & "\*.xls") Do While MyName <> "" Set mybook = Workbooks.Open(MyName) Call 転記(mybook.Sheets(1).Range("D6"), flg) flg = 1 Application.DisplayAlerts = False mybook.Close Application.DisplayAlerts = True MyName = Dir Loop Application.ScreenUpdating = True MsgBox ("集計処理が終わりました") End If End Sub Sub 転記(myRng, mytitle) Set keyRng = Range("A1") If keyRng = "" And keyRng.Offset(1) = "" Then Set topRng = keyRng Else Set topRng = keyRng.End(xlDown).Offset(1) End If Set mytbl = myRng.CurrentRegion If mytitle = 1 Then Set mytbl = mytbl.Offset(1, 0).Resize(mytbl.Rows.Count - 1, mytbl.Columns.Count) End If mytbl.Copy topRng.PasteSpecial xlPasteValues End Sub

  • エクセルVBAの転記について

    エクセル2013VBAで最終行を取得しての転記が上手くいきません。どのようにすれば良いかご教授ください。 簡単なサンプルを下記します。 Sub サンプル入力からのDBへの転記() Dim Sh1 As Worksheet Dim Sh2 As Worksheet Dim myRow As Long Set Sh1 = Worksheets("サンプル入力") Set Sh2 = Worksheets("サンプルDB") With Sh2 myRow = Range("A" & Rows.Count).End(xlUp).Row + 1 .Range("A" & myRow).Value = Sh1.Range("D4").Value .Range("B" & myRow).Value = Sh1.Range("F4").Value End With End Sub 入力内容を変えないテストでは (1)実行するとDBへの転記は問題なく出来ます。 (2)継続してマクロを実行しても問題なく転記が行われ、同じデータが蓄積されていきます。 入力内容を変更して引き続きマクロを実行すると挙動不審に陥ります。 現象としては (1)初めの行に何度も重ねて転記を行う。 (2)空白行を作り、その行に何度も転記を行ってしまう。 (3)空白行を作り、それ以降転記を実行し蓄積を行ってしまう。 入力シートには結合セル、リストを使用していますが、原因究明を行う中でこれが原因とは思えませんでした。 これがクリアできないと先に進めません。ぜひお力を貸してください。 宜しくお願い申し上げます。

  • エクセルVBAでファイル作成

    エクセルVBAで、データをフィルタで抽出し、別なBOOKの指定シートに転記し、名前をつけて保存したいのです。一応、下記のコードでテストは成功しました。 しかし下記コードでは1回ごとにデータの転記先を開かなくてはなりません。 処理する件数が多いので、できればいちいち新たに開き直さなくともよい方法はないでしょうか? 最初から開いておいて、転記後名前をつけて保存すると、開いていたファイルが閉じてしまい、うまくいきません。 別BOOKでなく別シートに転記して、そのシートをMoveして別ファイル保存ならわかるのですが、今回はどうしても別BOOKに転記しなければなりません。 よろしくお願いします。 Option Explicit Sub データ分割転記()   Dim myPth As String, fname As String   Dim myRng As Range, myC As Range   Dim i As Long, x As Long   Dim wb(2) As Workbook   Dim ws As Worksheet   Dim t As Single   t = Timer   Set wb(0) = ThisWorkbook   myPth = wb(0).Path   With wb(0).Sheets("Key")     Set myRng = .Range("A2", .Range("A2").End(xlDown)) 'KeyData   End With      For Each myC In myRng     Application.EnableEvents = False     Set wb(1) = Workbooks.Open(Filename:=myPth & "\20150806TEST.xlsm")     Set ws = wb(1).Sheets("List")        With wb(0).Sheets("DATA")       .Range("A1:J1").AutoFilter Field:=4, Criteria1:=myC.Value       .Range("A2", .Range("A2").SpecialCells(xlLastCell)).SpecialCells(xlCellTypeVisible).Copy ws.Range("A9")       .ShowAllData     End With     With ws       x = .Cells(Rows.Count, "A").End(xlUp).Row       myC.Offset(, 2).Value = x '行数確認       .Range("A9").Value = 1       If x > 9 Then         .Range("A9").AutoFill Destination:=.Range("A9:A" & x), Type:=xlFillSeries '連番       End If     End With     wb(1).SaveAs Filename:=myPth & "\作成ファイル\" & myC.Value & ".xlsm"     wb(1).Close (False)     Application.EnableEvents = True     i = i + 1   Next   MsgBox i & "件を完了" _   & vbCrLf & Timer - t & " Sec." End Sub *Application.EnableEvents = False を使っているのば別BOOKが持つイベントマクロを作動させないためです。

  • Excel VBAで確認なしで上書き保存

    起動中のBookでファイル名が Data.xlsのものを閉じたいと思いますが、 上書き確認メッセージを出さないように oExcel.DisplayAlerts = False を設定すると エラーになります。 CreateObject で作成した場合は、DisplayAlerts が使えるようですが、 すでに起動済みのBookを確認なしで上書き保存するにはどうしたらいい のでしょうか? Sub UnloadFile()   Dim myBook2 As Workbook   Dim myBook1 As Workbook    For Each myBook2 In Workbooks      If myBook2.Name = "Data.xls" Then        Set myBook1 = myBook2        myBook1.SaveAs myBook1.FullName        myBook1.Close      End If    Next myBook2    Set myBook1 = Nothing End Sub

  • VBA 初心者

    sheet1から、sheet2データを検索して抽出する練習をしているのですがerror"1104"が表示されます、なぜなのか分からないので投稿しました、よろしくお願いします。 sub test() dim sh1 as worksheets dim sh2 as worksheets dim  i  as  integer set sh1 = thisworkbook.worksheets("sheet1!") set sh2 = thisworkbook.worksheets("sheet2!") b = userform1.textbox1 for i = 1 to 10 sh1 .cells(i,2) = b b = b+1 x = sh1.cells(1,2) sh1.cells(i,3).value = worksheetfunction.vlookup(x,sh2.range("a1:d500"),2,false) next i end sub

  • VBAでセルのコピーをすると、エラーになる

    =IF(COUNTIF('5月'!B4:I13,E13)=0,"",COUNTIF('5月'!I:I,E13))というセルを コピーして、別のシートのセルに貼り付けたのですが、値が「0」の場合「””」が セルに張り付いてしまい、その後の計算ができません。 「””」を本当の空欄にするにはどうしたらいいのでしょうか? Sub 転記() Dim sh1 As Worksheet Dim sh2 As Worksheet Dim SN As String SN = Month(Now()) Set sh1 = Sheets(SN) Set sh2 = Sheets("差出票") sh1.Range("A35").End(xlUp).Offset(1) = sh2.Range("B9") sh1.Range("A35").End(xlUp).Offset(0, 1) = sh2.Range("F13") sh1.Range("A35").End(xlUp).Offset(0, 2) = sh2.Range("F14") sh1.Range("A35").End(xlUp).Offset(0, 3) = sh2.Range("F15") sh1.Range("A35").End(xlUp).Offset(0, 4) = sh2.Range("F16") sh1.Range("A35").End(xlUp).Offset(0, 5) = sh2.Range("F17") sh1.Range("A35").End(xlUp).Offset(0, 6) = sh2.Range("F18") sh1.Range("A35").End(xlUp).Offset(0, 7) = sh2.Range("F19") End Sub

  • EXCELのVBAを使用してフォルダー内の複数のデーターの集計処理を

    EXCELのVBAを使用してフォルダー内の複数のデーターの集計処理を 行いたいのですが1個目のデーター処理を行った後集計処理を行った後 集計シートを2個目のデーターに移動させたいのですが方法がわかりません。 下記のように集計表(原紙)を複数のデーターにコーピーはできるのですが Private Sub CommandButton1_Click() '集計表作成 Dim MyPath, MyBook, MyName MyPath = ThisWorkbook.Path & "¥" MyBook = ThisWorkbook.Name MyName = Dir(MyPath & "*.xls") Do While MyName <> "" If MyName <> MyBook Then Workbooks.Open Filename:=MyPath & MyName '一番左に集計表を貼り付ける Workbooks(MyBook).Worksheets(1).Copy Before:=Workbooks(MyName).Sheets(1) '"ここで集計処理後 次のBookへ移動" Workbooks(MyName).Save Workbooks(MyName).Close End If MyName = Dir Loop End Sub Copy部分をMoveにするとエラーメッセージがでてしまい 集計したシートを次々と移動させる方法がわかりません。 どのような方法で実行すれば宜しいでしょうか?

専門家に質問してみよう