質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

解決済

VBA:クラスモジュールの引数の減らし方について

hachi3156
hachi3156

総合スコア0

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

1回答

0評価

0クリップ

58閲覧

投稿2019/10/28 08:39

編集2022/01/12 10:58

イメージ説明    イメージ説明
ChangeDataクラスのShtAndShtプロシージャを用いてShee1の各品番と型式名、品名をSheet2のそれぞれのセルにコピーします

業務に必要なマスタデータを処理する過程でアクセスのフィールドのあるレコードの値をユーザーフォームのテキストボックスやワークシートのセルにコピーするなど、異なるオブジェクト間でデータのコピー・ペーストを行うことが多くなってきたので、それをChangeDataクラスで作ってみました。
データのやり取りをするのは、以下の6パターン(読み込み先と書き込み先)です
アクセスのレコード⇔ワークシートのセル
アクセスのレコード⇔ユーザーフォームのテキストボックス
ワークシートのセル⇔ユーザーフォームのテキストボックス

現在ChangeDataクラス内のそれぞれのプロシージャでforループを回して処理しているのですが、それをクラスモジュールではなく、標準モジュールからforループ処理をすることを考えています。
単純に考えたら、ShtAndSht関数にstartRowとEndRow、LengthOfArray を渡せば良いのかな思ったのですが、そうすると省略不可の引数が7個になってしまうので、これはさすがに多すぎると感じています。

そこで、引数を別の形で処理して減らす方法などありましたら教えていただければ幸いです。
今一つクラスモジュールの使い方をつかめていないので、何卒わかりやすい説明をお願い致します。

標準モジュール(自作クラスモジュールの現状の使用例)

Sub test1() Dim cd As ChangeData Set cd = New ChangeData Dim makeArr As MakeStrArrForSetObject Set makeArr = New MakeStrArrForSetObject Dim Readlist() As Variant Dim Writelist() As Variant Readlist() = makeArr.ArrPartNum Writelist() = makeArr.ArrPartNum 'このモジュールでループ処理を行いたい Call cd.SheAndSht("Sheet1", "Sheet2", Readlist(), Writelist()) End Sub

###クラスモジュール1 MakeStrArrForSetObj

Private Const Partnum = "品番" Private Const Model = "型式名" Private Const Item = "品名" Public Function ArrPartNum() As Variant() ArrPartNum = Array(PartNum, Model, Item) End Function

###クラスモジュール2 ChangeData

Public Sub SheAndSht(ByVal TarShtToREAD As String, ByVal TarShtToWRITE As String, ByRef ReadList() As Variant, ByRef WriteList() As Variant) Dim CntRow As Long Dim readobj As Object Dim writeobj As Object Dim StartRow As Long Dim EndRow As Long Dim LengthOfArray As Long Dim reObj As returnObject Set reObj = New returnObject StartRow = 3 EndRow = 10 'ここの二重ループをクラスモジュールの外に出し、さらに関数に渡す引数を減らしたい For CntRow = StartRow To EndRow For LengthOfArray = LBound(ReadList) To UBound(ReadList)     Set reObj.Cls_ws = Worksheets(TarShtToREAD)     Set readobj = reObj.SetObjToRead("CELL", ReadList(), LengthOfArray, CntRow)     Set reObj.Cls_ws = Worksheets(TarShtToWRITE)     Set writeobj = reObj.SetObjToWrite("CELL", WriteList(), LengthOfArray, CntRow)     writeobj.Value = readobj.Value Next LengthOfArray Next CntRow End Sub Public Sub ReadDBData(ByVal TarObjToWRITE As String, ByRef ReadList() As Variant, ByRef WriteList() As Variant, ByVal strSQL As String) Dim CntRow As Long Dim readobj As Object Dim writeobj As Object Dim LengthOfArray As Long Dim StartRow As Long Dim EndRow As Long Dim ADOCon As ADODB.Connection Dim ADORes As ADODB.Recordset Set ADOCon = initDb(ADODB_NAME, ADODB_PASS) Set ADORes = New ADODB.Recordset ADORes.Open strSQL, ADOCon Dim reObj As returnObject Set reObj = New returnObject '----標準モジュール記載 Set reObj.Cls_ADORes = Createobject("ADODB.recordset") Set reObj.Cls_Frm = UserForm1 '---- StartRow = 3 EndRow = 10 For CntRow = StartRow To EndRow 'リストの要素数 For LengthOfArray = LBound(ReadList) To UBound(ReadList) Set readobj = reObj.SetObjToRead("FIELD", ReadList(), LengthOfArray, CntRow) Set writeobj = reObj.SetObjToWrite(TarObjToWRITE, WriteList(), LengthOfArray, CntRow) writeobj.Value = readobj.Value Next LengthOfArray Next CntRow End Sub

###クラスモジュール3 returnObject

・クラス変数 Public Cls_ws As Worksheet Public Cls_ADORes As ADODB.Recordset Public Cls_Frm As UserForm Public Function SetObjToRead(ByVal strTarObj As String, ByRef Cls_strArrForSetObj() As Variant, ByVal TarCol As Long, Optional TarRowForCell As Long = 1) As Object 'データを読み込む(コピーする)オブジェクトを選択 Select Case strTarObj Case "CELL" Set SetObjToRead = ObjCell(Cls_strArrForSetObj(TarCol), TarRowForCell) Case "FIELD" Set SetObjToRead = ObjField(Cls_strArrForSetObj(TarCol)) Case "CONTROL" Set SetObjToRead = ObjControl(Cls_strArrForSetObj(TarCol)) End Select End Function Public Function SetObjToWrite(ByVal strTarObj As String, ByRef Cls_strArrForSetObj() As Variant, ByVal TarCol As Long, Optional TarRowForCell As Long = 1) As Object 'データを書き込む(ペーストする)オブジェクトを選択 Select Case strTarObj Case "CELL" Set SetObjToWrite = ObjCell(Cls_strArrForSetObj(TarCol), TarRowForCell) Case "FIELD" Set SetObjToWrite = ObjField(Cls_strArrForSetObj(TarCol)) Case "CONTROL" Set SetObjToWrite = ObjControl(Cls_strArrForSetObj(TarCol)) End Select End Function Private Function ObjCell(ByRef Cls_strForSetObj As Variant, ByVal TarRow As Long) As Range Set ObjCell = Cls_ws.Cells(TarRow, ColSlctByTitle(Cls_strForSetObj, Cls_ws)) End Function

###標準モジュール

Public Function ColSlctByTitle(ByVal Title As String, ByVal ws As Worksheet, Optional ByVal DefaultRow As Integer = StartRow) As Integer Dim CountCol As Integer Dim titleRow As Integer Dim MaxCol As Integer titleRow = DefaultRow ' タイトル行番号 With ws MaxCol = .Cells(DefaultRow, .Columns.Count).End(xlToLeft).Column For CountCol = 1 To MaxCol If .Cells(titleRow, CountCol).Text() = Title Then ColSlctByTitle = CountCol Exit Function ' 正常終了 End If Next End With 'エラー終了 Err.Description = ws.Name & "のタイトル行に指定文字列( " + Title + " ) が見つかりませんでした" Err.Raise (60000) MsgBox (Err.Description) End Function Public Function initDb(ByVal FileName As String, ByVal FilePass As String) As ADODB.Connection Dim ConnectionString As String '接続文字列 Dim DbFilePass As String 'データベースファイルのパス Dim DbFileName As String 'データベースファイルの名前 Dim ADOCon As ADODB.Connection 'データベース接続オブジェクト Dim strCon As String '接続文字列作成 ConnectionString = "Microsoft.ACE.OLEDB.12.0" DbFileName = FileName & ".accdb" Set ADOCon = New ADODB.Connection ' 接続文字列を作成する strCon = "Provider=" & ConnectionString & ";" & "Data Source=" & FilePass & DbFileName & ";" '接続する ADOCon.Open strCon Set initDb = ADOCon End Function

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

Youbun
Youbun

2019/10/29 05:55 編集

ぱっと見で思ったのですが、 ・そもそも「ChangeData」をクラスにする必要はあるのでしょうか? ・ReadList\(\)とWriteList\(\)の中身が変わる可能性はありますか?  テスト関数では常に同じ内容が入ってるっぽいのですが。。。 ・ReadList\(\)とWriteList\(\)を参照渡しで渡す必要性はありますか?  ないならまとめれる気がします。
hachi3156
hachi3156

2019/10/29 10:42

Youbun様 返信していただきありがとうございます。 ・そもそも「ChangeData」をクラスにする必要はあるのでしょうか? →オブジェクト指向を使うとプログラムを再利用や変更がしやすく、VBAではクラスモジュールがそれに該当すると聞いて、実際コードこそ全く同じではないものの、似たような処理を行っていたためそれらの共通する部分をまとめて使いまわせないかと考えて今回のようなものを作ってみた次第です ・ReadList\(\)とWriteList\(\)の中身が変わる可能性はありますか? →すみません、例が悪かったです。シート間のデータのやりとりの場合は両方とも同じになりますが、ReadListやWritelist内の文字列を使ってオブジェクトを返すようにしているので、シートとユーザーフォームやユーザーフォームやフィールドとのやりとりの場合は変わってきます ・ReadList\(\)とWriteList\(\)を参照渡しで渡す必要性はありますか? →よくよく考えたら必要なさそうです 教えていただいたサイトを参考に今一度クラスについて勉強いたします。
Youbun
Youbun

2019/10/30 10:00

・適切なデータ例に修正してくれたら何がしたいのか分かりやすくなる ・上げているソースコードに使ってない関数があり、崩していいのか分からないので  説明を加えてくれると分かりやすい ・ブックをまたいでやり取りするのか? 上記質問を質問に追記していただけると回答しやすいと思います

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。