• ベストアンサー

Setステートメントをまとめて記述する方法 (エクセル2000VBA)

お世話になります。 Setステートメントで以下のように書いて、シート名を省略して使っています。  Set a = ThisWorkbook.Worksheets("い")  Set b = ThisWorkbook.Worksheets("ろ")  Set c = ThisWorkbook.Worksheets("は") これをプロシージャ毎に書くとコードが長くなるので、先頭かどこかに1回書くだけで、全てのプロシージャで使えるようにしたいのですがどうしたら良いでしょうか? このようなプロシージャを実行したいのですが、 Private Sub CommandButton1_Click()  a.Range("A2").Value = "データ1"  b.Range("B4").Value = "データ2"  c.Range("C9").Value = "データ3" End Sub (他にもコマンドボタンやチェックボックス用のプロシージャがあります) Setステートメントだけを先頭に書くと、 「プロシージャの外では無効です」というエラーが出ましたので、 Public Sub hensuu()  Set a = ThisWorkbook.Worksheets("い")  Set b = ThisWorkbook.Worksheets("ろ")  Set c = ThisWorkbook.Worksheets("は") End Sub のようにしたら、「実行時エラー"424":オブジェクトが必要です」というエラーが出てしまいました。 どのようにしたらエラーが出ず正しく動くようになりますでしょうか?よろしくお願いします。

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

  • ベストアンサー
回答No.4

> ただ、シート数や順番、シート名など変更になる場合が多いので、1ヶ所変更したら置換などしなくても全てのコードが変更されるようにしたかったので シート数が変更になった時点で、別のコーディングが入ると思います。 シート名、シート数が変更になっただけであれば、 以下の方法で対処可能です。 No.3のコーディングを例にします。 【Sheet(い)】 Private Sub CommandButton1_Click() With ThisWorkbook.Sheets(SHEET1_NAME) .Range("A2").Value = "データ1" .Range("B4").Value = "データ2" .Range("C9").Value = "データ3" End With With ThisWorkbook.Sheets(SHEET2_NAME) .Range("A2").Value = "データ1" .Range("B4").Value = "データ2" .Range("C9").Value = "データ3" End With With ThisWorkbook.Sheets(SHEET3_NAME) .Range("A2").Value = "データ1" .Range("B4").Value = "データ2" .Range("C9").Value = "データ3" End With End Sub 【Module1】 Public Const SHEET1_NAME As String = "い" Public Const SHEET2_NAME As String = "ろ" Public Const SHEET3_NAME As String = "は" シート数が増えた場合にはModule1の定数を追加して下さい。 とりあえず、瞬間的に考えたらこれしか思いつきませんでした^^;

double12345
質問者

お礼

ご回答ありがとうございます。 シート名をModule1にまとめて書いておいたらいいんですね。これで変更箇所がひとつで済み、楽になりました! 個々のプロシージャにも、1行だけ Set W = Thisworkbook.Worksheets を追加し、 With W(SHEET1_NAME) .Range("A2").Value = "データ1" .Range("B4").Value = "データ2" .Range("C9").Value = "データ3" End With としてみました。書き忘れや変更もれがなくなりそうです。ありがとうございます。

その他の回答 (5)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

追伸です。Wendy02ですが、タイトルのご質問そのものは、変数をCollection にすれば、1つの変数で、Objectを複数個、保持できますが、それは、ひじょうに特殊な方法です。 私自身は、「シート数や順番、シート名など変更になる場合」を想定して作りますが、それは、隠し技のようなものです。 それよりも、ユーザー側が、ブック変更の禁止の方法をさせる方法を考えたほうがよいと思います。変更するのは、製作する側だけのものにします。 実際に、私自身は、そんな多くはありませんが、#5で示したようなローカル配列変数を使っています。Publicにする場合は配列変数では受け渡しはしません。1つのプロシージャの中で配列変数を作ります。Collectionの場合も同じです。ローカルの中で処理するようにします。手間のようですが、経験的に、そのほうがエラーが避けられます。

double12345
質問者

お礼

ご回答ありがとうございます。 Collectionについてヘルプなどを読んでみましたが、いまいちピンときませんでした…。まだまだ知識が足りないので、これからゆっくりでも理解していきたいと思います。 Wendy02さん、naktakさん、たくさんのご回答・アドバイスありがとうございました。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.5

こんばんは。 現実的な使い方でないと、どうしようもないので、後は、こんな使い方がありますね。 > ただ、シート数や順番、シート名など変更になる場合が多いので、1ヶ所変更したら置換などしなくても全てのコードが変更されるようにしたかったので 標準モジュール Public Const myWshName As String = "い,ろ,は" シートモジュール '---------------------------------- Private Sub CommandButton1_Click() Dim Wsh() As String  Wsh() = Split(myWshName, ",")  With ThisWorkbook  .Worksheets(Wsh(0)).Range("A2").Value = "データ1"  .Worksheets(Wsh(1)).Range("B4").Value = "データ2"  .Worksheets(Wsh(2)).Range("C9").Value = "データ3"  End With End Sub ただ、単に、置き換えただけに過ぎません。配列変数を置かない理由は、実際にやってみるとわかりますが、失敗する時があります。

double12345
質問者

お礼

ご回答どうもありがとうございます。 標準モジュールで定義した変数を、関数で配列のようにしているのですね。初めて見るコードや関数が多くてとても勉強になります。すごく便利そうですね。 また機会がありましたら使わせていただきます。

回答No.3

> Setでなく、文字列を省略するようなコードというのはありますでしょうか? With句で出来ます。 Private Sub CommandButton1_Click() With ThisWorkbook .Sheets("い").Range("A2").Value = "データ1" .Sheets("ろ").Range("B4").Value = "データ2" .Sheets("は").Range("C9").Value = "データ3" End With End Sub 1シートに複数処理をしたい場合は以下のようにします。 Private Sub CommandButton1_Click() With ThisWorkbook.Sheets("い") .Range("A2").Value = "データ1" .Range("B4").Value = "データ2" .Range("C9").Value = "データ3" End With With ThisWorkbook.Sheets("ろ") .Range("A2").Value = "データ1" .Range("B4").Value = "データ2" .Range("C9").Value = "データ3" End With With ThisWorkbook.Sheets("は") .Range("A2").Value = "データ1" .Range("B4").Value = "データ2" .Range("C9").Value = "データ3" End With End Sub ただこれは変数として保持は出来ないので、 複数プロシージャで処理する場合には 何度も記述する必要があります。 ですが、インスタンスを生成しない為、メモリの消費は抑えられます。 1つのオブジェクトなどに対して複数処理を行う際に コーディングの手間を省く事が出来ます。

double12345
質問者

お礼

ご回答どうもありがとうございます。 With句は、セルの書式設定をする時などによく使っていますが、こういう使い方もあるのですね。とても勉強になります。 でもこの場合ですと、「ThisWorkbook.Sheets("い")」という文字を沢山のプロシージャに何回も書かなければいけないので、できればそこを省略できるようにしたいのです…。 With句を使うとメモリの節約になるというのも初めて知りました。ありがとうございます!

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんにちは。 私には、インスタンスを作る以外には、実際にそのようなオブジェクトを、ずっと置いておくということはしませんね。本来は、オブジェクトコードネームを使うという方法もありますが、開発する時は、そのシートの目的や主旨を表したオブジェクトコードネームに、名称につけます。省略するためではありません。 もしするなら、標準モジュールにこのようにおいたらいかがですか? 戻し忘れをしない限りは、一旦、シートオブジェクトを入れれば、できますね。あくまでも、これも参考です。 Public a As Worksheet Public b As Worksheet Public c As Worksheet

double12345
質問者

お礼

ご回答ありがとうございます。 用語がほとんど分かりませんので、調べつつ拝見してるのですが、Setステートメントは入力を簡略化するものではないのですね…。字数を少なくするとかコードを見やすくするものだと思っていました。 Setでなく、文字列を省略するようなコードというのはありますでしょうか? よろしくお願いします。

回答No.1

あくまで参考例です。 【ThisWorkbook】 Private Sub Workbook_BeforeClose(Cancel As Boolean) Set xlWS = Nothing End Sub Private Sub Workbook_Open() Set xlWS = ThisWorkbook.Worksheets End Sub 【Sheet1(い)】 Private Sub CommandButton1_Click() xlWS("い").Range("A2").Value = "データ1" xlWS("ろ").Range("B4").Value = "データ2" xlWS("は").Range("C9").Value = "データ3" End Sub 【Module1】 Public xlWS As Sheets こんな事でしょうか? 動作確認済み。

double12345
質問者

お礼

ご回答どうもありがとうございます。 思っていた通りの動作になりました! 是非使わせていただきますね。 ただ、シート数や順番、シート名など変更になる場合が多いので、1ヶ所変更したら置換などしなくても全てのコードが変更されるようにしたかったので、シート名までも含めて、定義できないのは残念です…。 そういう設定はエクセルには不可能ということなのでしょうか…。

関連するQ&A

  • excelのifステートメントのテストで…

    御観覧ありがとうございます。 スパテクという本を買って、excelを勉強しようと、 サンプルを打ち込んでいて、何度かエラーになったりしましたが、 調べることや、入力ミスの確認で回避出来ていたのですが、 本通りに打っているのに、 「エラー438、オブジェクトは、このプロパティまたはメソッドをサポートしてません。」 と出ます。 エクセル2007です。入力したプロシージャは、 Option Explicit Dim nSample1_12 As Integer Sub Sample1_12() nSample1_12 = nSample1_12 + 1 ThisWorkbook.Worksheets("sheet1").Range("A1") = nSample1_12 End Sub Sub Sample1_13() Dim sA2 As String sA2 = ThisWorkbook.Worksheets("sheet1").Range("A2") If sA2 = "" Then ThisWorkbook.Worksheets("sheet1").Renge("A2") = "Sample1_13" ElseIf sA2 = "Sample1_13" Then ThisWorkbook.Worksheets("sheet1").Range("A2") = "基本の文法 ifステートメント" Else ThisWorkbook.Worksheets("sheet1").Range("A2") = "" End If End Sub このサンプル13を実行すると、A2にsample1_13と出るはずなそうなんですが…エラーになります。

  • VBAのエラーについて

    いつも識者の皆様にはお世話になっております。 Excel VBAのことで質問させてください。 Range("i23").Value = Application.VLookup(ThisWorkbook.Worksheets("aaa").Range("b5"), ThisWorkbook.Worksheets("data").Range("a2:b7"), 2, 0) というコードは通るのですが、 Range("i23").Value = Application.Left(VLookup(ThisWorkbook.Worksheets("aaa").Range("b5"), ThisWorkbook.Worksheets("data").Range("a2:b7"), 2, 0), 2) というleft関数を追加したコードだと「sub または function が定義されていません」というエラーになってしまいます。 VBAを始めたばかりなのですが、何か根本的な勘違いをしていますでしょうか? ちなみに Range("i23").Value = Application.Left(Application.VLookup(ThisWorkbook.Worksheets("aaa").Range("b5"), ThisWorkbook.Worksheets("data").Range("a2:b7"), 2, 0), 2) というコードも通りませんでした。 ご回答よろしくお願いいたします。

  • エクセルVBAの記述の違い

    下記の2つともA1:B2の中身を削除するものですが、test1の書き方だと対象となるシートがアクティブではないとエラーになります。test2は問題なし。 Cellsの書き方のほうが変数を使う時に便利なのですが、なんでこんな違いがでてしまうのでしょうか? Sub test1() Set ws1 = Worksheets("Sheet1") Set ws2 = Worksheets("Sheet2") ws1.Range(Cells(1, 1), Cells(2, 2)).ClearContents ws2.Range(Cells(1, 1), Cells(2, 2)).ClearContents End Sub Sub test2() Set ws1 = Worksheets("Sheet1") Set ws2 = Worksheets("Sheet2") ws1.Range("a1:b2").ClearContents ws2.Range("a1:b2").ClearContents End Sub

  • エクセルVBAのSetステートメントについて(長文)

    Sub PlusA002() Dim myTgCell As Range Dim myCounter As Integer Set myTgCell = Range("E2") Do Until myTgCell.Value = Empty If myTgCell.Value >= 80 Then myTgCell.Offset(0, 1).Value = "優" ElseIf myTgCell.Value < 80 And myTgCell.Value > 50 Then myTgCell.Offset(0, 1).Value = "良" Else myTgCell.Offset(0, 1).Value = "追試" End If Set myTgCell = myTgCell.Offset(1, 0) Loop End Sub このプログラムを例にして、Setステートメントについて質問します。Set myTgCell = Range("E2")を削除して実行すれば実行エラーという文言がでるし、またSet myTgCell = myTgCell.Offset(1, 0)を削除すればエクセルが固まるし、Setがこのプログラムに対して必要なのは判ります。しかし、Setがどのような役割を果たしているのかVisualBasicEditorのヘルプを見ても判りません。 どのような場面で使えるものなのですか?どなたか教えてください。

  • エクセルのフォームのVBAについて

    VBAがまったくわからないのに参考書を見て高度な事に挑戦しています フォームは作れてフォームをクリックやら入力やらして作ったOKボタンを押すと シート2のA1B1C1‥の列に入力文字だけが羅列されます。 しかし次にやろうとするとA2B2C2‥と下に行かず又A1B1C1‥の列の文字が変更になり続きません。何がいけないのでしょうか? Sub 入力() Dim LastRow As Long With Worksheets("sheet2") LastRow = Worksheets("sheet2").Range("A" & Rows.Count).End(xlUp).Row .Range("A" & LastRow).Value = Worksheets("sheet1").Range("A5").Value .Range("B" & LastRow).Value = Worksheets("sheet1").Range("A7").Value .Range("C" & LastRow).Value = Worksheets("sheet1").Range("A8").Value .Range("D" & LastRow).Value = Worksheets("sheet1").Range("A10").Value End With End Sub と参考書とおりいれたのですが‥。教えて下さい。

  • Excel VBA 構文をすっきりさせたい

    いつもお世話になっています。 次のような構文を使って、データを別シートに転送するVBAを作成しました。 転送するデータが多い場合、構文が延々続くことになります。 もっとすっきりと記述する方法がありましたらぜひ教えてください。 お力添え、よろしくお願いします。 Sub データ() With ActiveSheet Dim last last = ActiveSheet.Range("b" & Rows.Count).End(xlUp).Row + 1 .Range("b" & last).Value = Worksheets(2).Range("b2").Value .Range("c" & last).Value = Worksheets(2).Range("c2").Value .Range("d" & last).Value = Worksheets(2).Range("d2").Value     以下同様に続く・・・・ End With End Sub

  • 型が一致しません・・・VBA

    困っています、、 このコードを実行するとなぜか 「型が一致しません」と言われてしまいます しかしF8を使い順番にやっていくとそのまま実行されます Option Explicit Dim wsDetail As Worksheet Dim wsData As Worksheet Dim wsMES As Worksheet Public Sub meisai() Call 基本 Call 職務 Call 時間外 Call 補助 Call その他 Call 通勤 End Sub Private Sub 基本() Set wsDetail = Worksheets("給与明細") Set wsData = Worksheets("データ入力") Set wsMES = Worksheets("MES歩率表") wsDetail.Range("D10") = wsData.Range("C5").Value End Sub Private Sub 職務() Set wsDetail = Worksheets("給与明細") Set wsData = Worksheets("データ入力") Set wsMES = Worksheets("MES歩率表") wsDetail.Range("H10") = wsData.Range("C8").Value * Range("C5").Value End Sub Private Sub 時間外() Set wsDetail = Worksheets("給与明細") Set wsData = Worksheets("データ入力") Set wsMES = Worksheets("MES歩率表") wsDetail.Range("L10") = wsData.Range("C14").Value _ * Range("C16").Value * wsMES.Range("C4").Value End Sub Private Sub 補助() Set wsDetail = Worksheets("給与明細") Set wsData = Worksheets("データ入力") Set wsMES = Worksheets("MES歩率表") wsDetail.Range("P10") = wsData.Range("C19").Value End Sub Private Sub その他() Set wsDetail = Worksheets("給与明細") Set wsData = Worksheets("データ入力") Set wsMES = Worksheets("MES歩率表") wsDetail.Range("AB10") = wsData.Range("C21").Value End Sub Private Sub 通勤() Set wsDetail = Worksheets("給与明細") Set wsData = Worksheets("データ入力") Set wsMES = Worksheets("MES歩率表") wsData.Range("C27") = Application.RoundUp(wsData.Range("C25").Value * 2 * 0.083 * _ Range("C24").Value * Range("C23").Value, 1) wsDetail.Range("D13") = Application.WorksheetFunction.Round _ (wsData.Range("C27").Value * Range("C26").Value * 1.08, 0) End Sub 原因がさっぱりわからないのでどなたかよろしくお願いいたします<m(__)m>

  • VBA Setステートメント

    エクセル2002使用です。 B列に本日の日付が入るようにワークシートに関数(DAY関数)が入っています。 そのB列を検索して、同じ日付け(数字)がなければ、今日の日付を入力するVBAを組もうと思っているのですが、 Setステートメントで実行時エラー13になります。 ご教示いただけませんでしょうか? Private Sub CommandButton1_Click() ' 出勤ボタン B列に同日日付があればキャンセル Dim tuki, Hiduke1 As String Dim Hiduke1kekka As Variant tuki = Range("B3").Value Hiduke1 = Range("D3").Value Worksheets(tuki & "月").Activate Set Hiduke1kekka = ActiveSheet.Columns("B:B") _ .Find(What:=Hiduke1, After:=ActiveCell, LookIn:=xl, LookAt _ :=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _ False, MatchByte:=False, SearchFormat:=False) If Hiduke1kekka Is Nothing Then ActiveSheet.Range("D1000").End(xlUp).Select Selection.Value = "出" Worksheets("sheet1").Activate Else Worksheets("sheet1").Activate Exit Sub End If 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のSETステートメントについて

    マクロを組み込んだエクセルファイルが完成したのですが、ファイルサイズが大きくなってしまった ため、ファイルサイズを軽くするために現在 試行錯誤を繰り返しています。(シート数:50シート) ファイルサイズを軽くするために今までに取り組んできたのは下記の9項目です。 ・数式を値に変換 ・シートイベントプロシージャをThisWorkbookイベントに変換してマクロ構文を簡素化 ・隠れオブジェクトを全て削除(オブジェクト数を最小限・最小サイズに抑える) ・条件付書式、入力規則、名称登録を最小限に抑える ・必要な条件付書式のセル番地には必ず 『 $ 』 を付ける ・Offset 構文を最小限に抑える ・未使用セルの削除(最終セルの位置を正常化) ・Call マクロを多用してマクロ構文の情報量を極力減らす ・型に応じた変数宣言を徹底(バリアント変数扱いを最小限に抑える) ただ、『 型に応じた変数宣言 』 のSETステートメントの正しい使い方について私自身が良く理解 をしていないためにご指導を頂きたく投稿をさせて頂きました。不明なのは下記の2点です。 (1)『 SET a = ○○○○ 』 はオブジェクト型変数に対してのみ使用するものなのでしょうか?   データ型(Date)や文字列型(String)の変数に対してはSETステートメントは使用しないもの   なのでしょうか?仮にデータ型や文字列型変数に対してSETステートメントを使用した場合の   メリットとデメリットについて教えて下さい。もしかして、データ型や文字列型の変数の場合は   ただ単純に 『 SET 』 の文字が省略されているだけなのでしょうか。この基本的な部分の   理解ができていないので、理屈が分からずに困っております。 (2)『 SET a = Nothing 』 の対応はどこまで必要なのでしょうか?   上記(1)の質問にも絡むのですが、メモリリソースを開放してファイルサイズを軽くするためには   『 SET a = Nothing 』 が有効であるという情報がインターネット上に多数掲載されてますが   データ型や文字列型変数に対してもプロシージャの末尾に 『 SET a = Nothing 』 の構文   を付け加えた方がファイルサイズが軽くなるものなのでしょうか?   また、下記マクロ処理の場合にも 『 SET a = Nothing 』 の構文は必要なのでしょうか?        'Shをオブジェクト型変数として宣言     Dim Sh As Worksheet           :           :     '全てのシートに対して以下の処理を実行     For Each Sh In Worksheets            固有のシートに対してではなく全てのシートに           :                      対してマクロを実行する処理においても           :                      末尾に 『 SET a = Nothing 』 の構文を     '次のブックに対しても同様の処理を実行   付け加えた方がファイルサイズが軽くなる     Next Sh                        ものなのでしょうか? とにかく、正攻法でファイルサイズを軽くする方法を探しています。コメントが長くなり過ぎてしまい ましたが、『 SETステートメントの正しい使用方法 』、『 ファイルサイズを軽くするための裏技 』 などについて、ご存知の方がいらっしゃいましたら是非教えて頂けますよう宜しくお願いします。

専門家に質問してみよう