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

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

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

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

Q&A

解決済

2回答

3028閲覧

VBAでのプロパティ型に関するオーバーロード

yuujiMotoki

総合スコア90

VBA

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

0グッド

0クリップ

投稿2018/09/21 07:25

編集2018/09/21 07:53

VBAでコレクションクラスを使って、シート上に並んだデータを読み込む関数を書いています。

プロパティが異なるクラスに対する処理のために、同じような関数を書くことになりますが、
型宣言の部分以外は、ルーチンがまったく同じです。

できればオブジェクト指向的に、使い回しをしたいのですが、この場合は関数のオーバーロードなのか、
インターフェイスによる継承なのか分かりませんが、コレクションの中に入れるオブジェクトの型宣言の部分を
汎化するには、どうしたらいいでしょうか?
(他の言語なら、さくっとできるのかもしれませんが、現時点ではアイデアが無くて困っています)

objshtというのが、ワークシートになっており、
この名前で、型宣言を可変にしたいです

vba

1(clsCollection) 2 3'項目を読み込むクラス 4Public Function 項目読込(ByVal objsht As Variant) As Collection 5 Dim ItemList As New Collection 6 Dim endflg As Boolean 7 row = 2 8 9 Do 10 With New clsSchedule 11 Set .WST = objsht 12 endflg = .セル読込(row) 13 ItemList.Add .Self 14 row = row + 1 15 End With 16 Loop While endflg = True 17 18 Set 項目読込 = ItemList 19 20End Function 21 22

VBA

1 2(clsSchedule) 3 4Option Explicit 5Public ID As Long 6Public 項目 As String 7Public 詳細項目 As String 8Public 作業分類 As Long 9Public ステータス As Boolean 10Public 計画者 As String 11Public 担当者 As String 12Public 予定開始時間 As Date 13Public 予定終了時間 As Date 14Public 実績開始時間 As Date 15Public 実績終了時間 As Date 16Public 実績工数 As Long 17Public 投入 As Long 18Public 取出 As Long 19Public ウェイト As Long 20 21Const MAX_COLUMN = 20 22Private DST As Worksheet 23 24Public Property Get Self() As clsSchedule 25 Set Self = Me 26End Property 27 28 29Public Function セル読込(ByVal row As Long) As Boolean 30 If DST.Cells(row, 1) = "" And DST.Cells(row, 2) = "" Then 31 セル読込 = False 32 Exit Function 33 End If 34 35 With New clsStrage 36 .value(row, 1, MAX_COLUMN) = 0 37 Set .WST = DST 38 39ID = .DATA 40項目 = .DATA 41詳細項目 = .DATA 42作業分類 = .DATA 43ステータス = .DATA 44計画者 = .DATA 45担当者 = .DATA 46予定開始時間 = .DATA 47予定終了時間 = .DATA 48実績開始時間 = .DATA 49実績終了時間 = .DATA 50実績工数 = .DATA 51 52投入 = .DATA 53取出 = .DATA 54 55 End With 56 57 If ウェイト < 1 Then ウェイト = 1 58 セル読込 = True 59 60End Function 61 62Property Set WST(ByVal newVal As Worksheet) 63 Set DST = newVal 64End Property 65

##自己解決方法

一応、自分なりに書いてみましたが、これでもかなり無駄が多いコードです。

VBA

1 2Option Explicit 3Private row As Integer 4 5'項目を読み込むクラス 6Public Function 読込(ByVal objsht As Variant) As Collection 7 Dim ItemList As New Collection 8 Dim endflg As Boolean 9 10 Debug.Print objsht.name 11 12 row = 2 13 14Do 15 16 Select Case objsht.name 17 18 Case "チャートクエリ" 19 With New clsSchedule 20 Set .WST = objsht 21 endflg = .セル読込(row) 22 ItemList.add .Self 23 row = row + 1 24 End With 25 26 Case "ビルド" 27 With New clsPeople 28 Set .WST = objsht 29 endflg = .セル読込(row) 30 ItemList.add .Self 31 row = row + 1 32 End With 33 34 Case "品種" 35 With New clsSchedule 36 Set .WST = objsht 37 endflg = .セル読込(row) 38 ItemList.add .Self 39 row = row + 1 40 End With 41 42 End Select 43 44Loop While endflg = True 45 46 Set 読込 = ItemList 47 48End Function

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

あまりにも使う人が少ない機能ですが「Implements」というものがあります。
一応インターフェースらしき機能です。Implementsしたオブジェクトは
1.Publicのすべての実装を強制されます。1つでも未定義の場合コンパイルでエラーを吐きます。
2.Implements元のオブジェクトにダウンキャストできるようになります。

というわけでこんな感じでしょうか。ExcelVBAは全く触らないので感覚で書いています。

vba

1(clsIData) 2Option Explicit 3 4' インターフェース専用なので中身なし、書いても今回は使えません。 5Public Function セル読込(ByVal row As Long) As Boolean 6 7End Function 8 9Public Property Get Self() As Object 10 11End Property 12 13Public Property Set WST(ByVal newVal As Worksheet) 14 15End Property

clsScheduleはclsIDataをImplementsします

vba

1(clsSchedule) 2Option Explicit 3 4' ###################### 5' ここ! 6' ###################### 7Implements clsIData 8 9Public ID As Long 10Public 項目 As String 11Public 詳細項目 As String 12Public 作業分類 As Long 13Public ステータス As Boolean 14Public 計画者 As String 15Public 担当者 As String 16Public 予定開始時間 As Date 17Public 予定終了時間 As Date 18Public 実績開始時間 As Date 19Public 実績終了時間 As Date 20Public 実績工数 As Long 21Public 投入 As Long 22Public 取出 As Long 23Public ウェイト As Long 24 25Const MAX_COLUMN = 20 26Private DST As Worksheet 27 28Private Property Get clsIData_Self() As Object 29 Set clsIData_Self = Me 30End Property 31 32Private Property Set clsIData_WST(ByVal newVal As Excel.Worksheet) 33 Set DST = newVal 34End Property 35 36Private Function clsIData_セル読込(ByVal row As Long) As Boolean 37 If DST.Cells(row, 1) = "" And DST.Cells(row, 2) = "" Then 38 clsIData_セル読込 = False 39 Exit Function 40 End If 41 42 With New clsStrage 43 .Value(row, 1, MAX_COLUMN) = 0 44 Set .WST = DST 45 46 ID = .Data 47 項目 = .Data 48 詳細項目 = .Data 49 作業分類 = .Data 50 ステータス = .Data 51 計画者 = .Data 52 担当者 = .Data 53 予定開始時間 = .Data 54 予定終了時間 = .Data 55 実績開始時間 = .Data 56 実績終了時間 = .Data 57 実績工数 = .Data 58 59 投入 = .Data 60 取出 = .Data 61 62 End With 63 64 If ウェイト < 1 Then ウェイト = 1 65 clsIData_データ読込 = True 66End Function 67

Implementsすると元オブジェクトのPublicをすべて実装しなければなりません。
メソッド名などは「clsIData_セル読込」みたいな感じで先頭にクラス名が付きます。

使うときはこうなります。

vba

1Option Explicit 2Private row As Integer 3 4'項目を読み込むクラス 5Public Function 読込(ByVal objsht As Variant) As Collection 6 Dim ItemList As New Collection 7 Dim endflg As Boolean 8 ' ダウンキャスト用 9 Dim Dataobj as clsIData 10 11 Debug.Print objsht.name 12 13 row = 2 14 15Do 16 ' 一応気持ち悪いので 17 set Dataobj = Nothing 18 19 Select Case objsht.name 20 21 Case "チャートクエリ","品種" 22 ' 代入できる 23 Set Dataobj = New clsSchedule 24 ' 元オブジェクトにキャストするとclsScheduleのPublicにアクセス可能 25 'Dim sch as clsSchedule 26 'set sch = Dataobj.Self 27 'sch.項目 = "test" 28 Case "ビルド" 29 ' claPeopleがclsIDataをImplementsしていればこれも入る 30 Set Dataobj = New clsPeople 31 End Select 32 33 ' それぞれの持つオブジェクトのWST,セル読込で実行可能 34 With Dataobj 35 Set .WST = objsht 36 endflg = .セル読込(row) 37 ItemList.add .Self 38 End With 39 row = row + 1 40Loop While endflg = True 41 42 Set 読込 = ItemList 43 44End Function

ぶっちゃけると「VBAでここまでやりますか…」ってなります。
特にすべての実装を強制されるのは思っているよりもきつい(きつかった)です。委譲ができないので。
ダック・タイピングの方がはるかに簡単で「VBAらしい」としている人が多いですね。
インターフェースを直すとなったら大変ですがバグは出にくくなると思います。

投稿2018/09/21 13:20

編集2018/09/24 23:54
sousuke

総合スコア3828

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

以下のようなプロシージャを作成するのが一番手っ取り早そうです。

vba

1Public Function NewMyClass(ByVal objsht As Excel.Worksheet) As Object 2 Select Case objsht.Name 3 Case "チャートクエリ", "品種" 4 Set NewMyClass = New clsSchedule 5 Case "ビルド" 6 Set NewMyClass = New clsPeople 7 Case Else 8 Err.Raise 5 9 End Select 10 11 Set NewMyClass.WST = objsht 12 13End Function

使用例

vba

1Public Function 項目読込2(ByVal objsht As Variant) As Collection 2 Dim ItemList As New Collection 3 Dim endflg As Boolean 4 Row = 2 5 6 Do 7 With NewMyClass(objsht) 8 endflg = .セル読込(Row) 9 ItemList.Add .Self 10 Row = Row + 1 11 End With 12 Loop While endflg = True 13 14 Set 項目読込2 = ItemList 15 16End Function

投稿2018/09/21 09:16

編集2018/09/21 11:17
imihito

総合スコア2166

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問