Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


2553 / 13645 ツリー ←次へ | 前へ→

【67265】バージョンの違いによる引数変化の対応 ぴのぽ 10/11/18(木) 16:30 質問[未読]
【67266】Re:バージョンの違いによる引数変化の対応 UO3 10/11/18(木) 18:20 発言[未読]
【67267】Re:バージョンの違いによる引数変化の対応 ichinose 10/11/18(木) 18:30 発言[未読]
【67268】Re:バージョンの違いによる引数変化の対応 ichinose 10/11/18(木) 20:53 発言[未読]
【67270】Re:バージョンの違いによる引数変化の対応 ぴのぽ 10/11/19(金) 9:56 お礼[未読]
【67278】Re:バージョンの違いによる引数変化の対応 ichinose 10/11/19(金) 20:03 発言[未読]
【67279】例1 ichinose 10/11/19(金) 20:11 発言[未読]
【67280】Re:例2 ichinose 10/11/19(金) 20:18 発言[未読]
【67281】Re:例3 ichinose 10/11/19(金) 20:30 発言[未読]
【67282】追伸 ichinose 10/11/19(金) 21:02 発言[未読]
【67302】Re:追伸 ぴのぽ 10/11/22(月) 14:51 お礼[未読]
【67269】Re:バージョンの違いによる引数変化の対応 neptune 10/11/18(木) 22:17 発言[未読]
【67271】Re:バージョンの違いによる引数変化の対応 ぴのぽ 10/11/19(金) 9:59 お礼[未読]
【67272】Re:バージョンの違いによる引数変化の対応 ぴのぽ 10/11/19(金) 10:24 質問[未読]
【67274】Re:バージョンの違いによる引数変化の対応 ぴのぽ 10/11/19(金) 11:20 質問[未読]
【67275】Re:バージョンの違いによる引数変化の対応 neptune 10/11/19(金) 11:53 発言[未読]
【67286】Re:バージョンの違いによる引数変化の対応 熊谷隆史 10/11/20(土) 8:24 発言[未読]
【67297】Re:バージョンの違いによる引数変化の対応 neptune 10/11/21(日) 21:12 お礼[未読]
【67276】Re:バージョンの違いによる引数変化の対応 neptune 10/11/19(金) 12:00 発言[未読]
【67277】Re:バージョンの違いによる引数変化の対応 ぴのぽ 10/11/19(金) 13:31 お礼[未読]

【67265】バージョンの違いによる引数変化の対応
質問  ぴのぽ  - 10/11/18(木) 16:30 -

引用なし
パスワード
   はじめまして。
VBAに初めて携わってみて疑問に思ったことを投稿させていただきます。

Excelのバージョンによって、VBAのメソッドの引数の数等が違うものがありますが、
様々なバージョンに対応する上でどのようにしたらよいでしょうか。


if Application.Version == 10 Then
  xxxx(○○○, ○○○)
Else
  xxxx(○○○, ○○○,○○○, ○○○)
End If

おおまかな例ですが、上のようなソースだと、当然ではございますがコンパイルエラーになってしまいます。
やりたいこととしては、使用しているエクセルのバージョン情報を取得し、それによって処理を変え、他の処理はコンパイルも通らないようにしたいです。

ご助力の方、よろしくお願いします。

【67266】Re:バージョンの違いによる引数変化の対応
発言  UO3  - 10/11/18(木) 18:20 -

引用なし
パスワード
   ▼ぴのぽ さん:

こんにちは

大原則は(ちがっているかもしれませんが)、使われるであろう、一番低いバージョンで作成。
(おそらく、上位バージョンでは下位互換をしているだろうという希望的観測で)

どうしても上位バージョンの機能をつかったロジックを書いた場合は、
実行の最初にバージョンをチェックして、低ければ、メッセージを出して終了させる。

こんなところではないでしょうか?

【67267】Re:バージョンの違いによる引数変化の対応
発言  ichinose  - 10/11/18(木) 18:30 -

引用なし
パスワード
   ▼ぴのぽ さん:
こんばんは。

>はじめまして。
>VBAに初めて携わってみて疑問に思ったことを投稿させていただきます。
>
>Excelのバージョンによって、VBAのメソッドの引数の数等が違うものがありますが、
>様々なバージョンに対応する上でどのようにしたらよいでしょうか。


dim Obj as object
set obj=xxxx
>if Application.Version == 10 Then
  obj.method ○○○, ○○○
>Else
  obj.method ○○○, ○○○,○○○, ○○○
>End If

というように Object変数を使ったらどうでしょうか?

【67268】Re:バージョンの違いによる引数変化の対応
発言  ichinose  - 10/11/18(木) 20:53 -

引用なし
パスワード
   CallbyName を使う方法もありそうですが、
これは CallbyName関数調べて試してみてください

【67269】Re:バージョンの違いによる引数変化の対応
発言  neptune  - 10/11/18(木) 22:17 -

引用なし
パスワード
   ▼ぴのぽ さん:

Helpの
visual basic プログラミングのヒント
 ---条件付きコンパイル
は使えませんかね?

#基本は一番古いバージョンでなるたけ新しい手法で開発、VB定数は
バージョン間で変化することがあるから、自前で定数としておく。
のが楽チンかと思います。

【67270】Re:バージョンの違いによる引数変化の対応
お礼  ぴのぽ  - 10/11/19(金) 9:56 -

引用なし
パスワード
   ▼ichinose さん:
>CallbyName を使う方法もありそうですが、
>これは CallbyName関数調べて試してみてください

返信ありがとうございます。

結果的にはCallbyNameで通りました。

dim Obj as object
set obj=xxxx
if Application.Version == 10 Then
obj.method ○○○, ○○○
Else
obj.method ○○○, ○○○,○○○, ○○○
End If

上記方法の場合、バージョンによっては存在しないメソッドがきた場合対応できるかが不明だったため、
CallbyNameの方で行いました。

Sub ボタン1_Click()
  
 If (Application.Version >= 10) Then
  CallByName Assistant, "Attention", _
      "ご利用のバージョンは2002以上です。", _
      msoAlertButtonYesAllNoCancel, _
      msoAlertIconCritical, _
      msoAlertDefaultSecond, _
      msoAlertCancelFirst, _
      False

 Else
 
    Worksheets("Sheet1").Range("A1:F1").Value = "EXCEL VBA"

End Sub

簡単ではありますが、このような形です。

ありがとうございました。

【67271】Re:バージョンの違いによる引数変化の対応
お礼  ぴのぽ  - 10/11/19(金) 9:59 -

引用なし
パスワード
   お世話になっております。
ご返信ありがとうございました。
ichinoseさんの返信にありました、CallbyNameで行うことにいたしました。

Sub ボタン1_Click()
  
 If (Application.Version >= 10) Then
  CallByName Assistant, "Attention", _
      "ご利用のバージョンは2002以上です。", _
      msoAlertButtonYesAllNoCancel, _
      msoAlertIconCritical, _
      msoAlertDefaultSecond, _
      msoAlertCancelFirst, _
      False

 Else
 
    Worksheets("Sheet1").Range("A1:F1").Value = "EXCEL VBA"

End Sub

上記のような形で行うことにいたしました。

どうもありがとうございました。

【67272】Re:バージョンの違いによる引数変化の対応
質問  ぴのぽ  - 10/11/19(金) 10:24 -

引用なし
パスワード
   申し訳ございません。

一度お礼言ってからいうのもあれなのですが、
CallbyNameがVB6.0からの実装でした。
Excel97も視野に入れている場合、他の方法はありますでしょうか。

条件付コンパイルは元々考えていたのですが、各環境毎に定数を書き換えてあげないといけない点からやめました。
下の環境を基準に作成はしますが、下の環境でも存在するメソッドでも、上の環境だと引数が違う等が発生し、また、エラーメッセージを返すということができないため(処理は必ず行わないといけないため)、何がしかの方法で処理を行わなければいけません。

よろしくお願いします。

【67274】Re:バージョンの違いによる引数変化の対応
質問  ぴのぽ  - 10/11/19(金) 11:20 -

引用なし
パスワード
   度々申し訳ございません。

もう一度条件付コンパイルについて調べたのですが
#if VBA6 Then
での振り分けということでしょうか。

#if VBA6 Then
 if (Application.Version >= 10) Then  ' Excel2002以降
    CallbyName xxxxx
 Else                 ' Excel2000
    CallbyName xxxxx
 End If
#Else
 ' Excel97の処理
#End If

勘違いでしたら申し訳ございません。

皆さんのアドバイスを元に作成してみたのですが、これで可能でしたらこれで行こうかと思っております。

【67275】Re:バージョンの違いによる引数変化の対応
発言  neptune  - 10/11/19(金) 11:53 -

引用なし
パスワード
   ▼ぴのぽ さん:

>もう一度条件付コンパイルについて調べたのですが
>#if VBA6 Then
>での振り分けということでしょうか。
10年も前の話なんで記憶のなしになりますが、
XL97まではVBA5で、XL2000からVBA6になりました。文字列関数やaddressofが
追加されてうれしかったもんです。
で、その後はVBAは進化してないと思います。つまりVBA6のまんま。
ここまでは多分間違ってはないと思います。


>#if VBA6 Then
> if (Application.Version >= 10) Then  ' Excel2002以降
>    CallbyName xxxxx
> Else                 ' Excel2000
>    CallbyName xxxxx
> End If
>#Else
> ' Excel97の処理
>#End If
>
で、多分これでいけるそうですが、環境がないので検証できません。
実機で確認するのが一番確実なのでそうしてください。
・・・・間違ってたらごめんなさい。

【67276】Re:バージョンの違いによる引数変化の対応
発言  neptune  - 10/11/19(金) 12:00 -

引用なし
パスワード
   ▼ぴのぽ さん:
今思ったものすごい無責任発言ですが、
>下の環境を基準に作成はしますが、下の環境でも存在するメソッドでも、
>上の環境だと引数が違う等が発生し、また、エラーメッセージを返すという
>ことができないため(処理は必ず行わないといけないため)、何がしかの方法
>で処理を行わなければいけません
上の環境でも動作するメソッドを下のvba5で関数化できたら
良いですね。よくやった例で例えればsplit関数とかはそういう風によくやったもんです。

【67277】Re:バージョンの違いによる引数変化の対応
お礼  ぴのぽ  - 10/11/19(金) 13:31 -

引用なし
パスワード
   ▼neptune さん:
>▼ぴのぽ さん:
>今思ったものすごい無責任発言ですが、
>>下の環境を基準に作成はしますが、下の環境でも存在するメソッドでも、
>>上の環境だと引数が違う等が発生し、また、エラーメッセージを返すという
>>ことができないため(処理は必ず行わないといけないため)、何がしかの方法
>>で処理を行わなければいけません
>上の環境でも動作するメソッドを下のvba5で関数化できたら
>良いですね。よくやった例で例えればsplit関数とかはそういう風によくやったもんです。

お返事ありがとうございます。

私も、この方法が不可能であれば97でそういったもの(今回でいうとCallByName関数にあたるもの)を実装するしかないかなと思っておりました。
なかなか厳しいかもしれませんが。。。
ともあれ、まだ97での動作確認は手元の環境の関係上とれてないのですが、コンパイラ定数での振り分けの後に、2000以降のバージョンに関してはCallByName関数で対応するという方法で可能であればこの方法でいこうかなと思っております。

また何かあればご助言いただければと思います。
質問にお付き合いいただきありがとうございましたm(_ _)m

【67278】Re:バージョンの違いによる引数変化の対応
発言  ichinose  - 10/11/19(金) 20:03 -

引用なし
パスワード
   こんばんは。
私も最初は、条件付コンパイルを使って・・・、
例えば、インストーラーも作成して、このインストーラーが
Vbprojectを操作して定数設定も行えば・・・。
なんておぼろげに考えていましたが、昨日は、説明を色々記述し始めたら眠くなってきまして・・・。
私、最近は、朝4時起きなもので・・・。

これは、さておき・・・。

>結果的にはCallbyNameで通りました。
>上記方法の場合、バージョンによっては存在しないメソッドがきた場合対応できるかが不明だったため、
>CallbyNameの方で行いました。

CallbyNameは、信頼できて、Object型変数を使うのは、不明だ という
境界は、何だったのでしょうかねえ??

これ、要は、コンパイルエラーにならなければ良いのですよね?
古いバージョンで実行時エラーになるのは、当然ですよね?
よって、バージョンで処理を分岐させるのですから・・・・。

Object型変数を使って対象オブジェクトを参照すれば、
メソッドのチェックまでコンパイル時にはしないはずですよ。
だって、コンパイラは、見えてないものメソッドやプロパティまでは・・・。

次投稿にて、Object型変数に使う例を三つほど提示しますので、
検討してみてください。

【67279】例1
発言  ichinose  - 10/11/19(金) 20:11 -

引用なし
パスワード
   例1

新規ブックにて、

クラスモジュール作成してください(クラス名は、既定名のClass1)

このClass1のモジュールには

'==========================================================
Option Explicit
Function method_add(x As Double, y As Double) As Double
  method_add = x + y
End Function

という足し算の答えを返す method_add というメソッドだけです。


標準モジュールに

Sub test1()
  Dim cls As Class1
  Set cls = New Class1
  MsgBox cls.method_add(15, 23)
  MsgBox cls.aaa(15, 12)
End Sub

これを実行すると、

MsgBox cls.aaa(15, 12)
↑ここがコンパイルエラーになります。

が、
Sub test1()
  Dim cls As Class1
  Set cls = New Class1
  MsgBox cls.method_add(15, 23)
  'MsgBox cls.aaa(15, 12) ここは、コメント化しておく
End Sub
Sub test2()
  Dim cls As Object
  Set cls = New Class1
  MsgBox cls.method_add(15, 23)
  MsgBox cls.aaa(15, 12)
End Sub

test2を実行すると、コンパイルエラーにはならず、
MsgBox cls.method_add(15, 23)
↑この結果の38は、表示され、
MsgBox cls.aaa(15, 12)
この実行時にエラーになります。これは、当たり前
つまり、プロシジャーの実行はされていることになります。

【67280】Re:例2
発言  ichinose  - 10/11/19(金) 20:18 -

引用なし
パスワード
   例2

新規ブックにて、
参照設定で「Microsoft Scripting Runtime」にチェックして
FSOのFileSystemObject型の参照が可能にして置いてください。


標準モジュールに

Sub test3()
  Dim fso As FileSystemObject
  Set fso = CreateObject("scripting.filesystemobject")
  MsgBox fso.Drives.Count
  MsgBox fso.aaaa
End Sub

このtest3を実行すると、

MsgBox fso.aaaa
↑ここがコンパイルエラーになります。

が、

Sub test3()
  Dim fso As FileSystemObject
  Set fso = CreateObject("scripting.filesystemobject")
  MsgBox fso.Drives.Count
  'MsgBox fso.aaaa  ここは、コメント化しておく
End Sub
Sub test4()
  Dim fso As Object
  Set fso = CreateObject("scripting.filesystemobject")
  MsgBox fso.Drives.Count
  MsgBox fso.aaaa
End Sub

test4を実行すると、コンパイルエラーにはならず、
MsgBox fso.Drives.Count
>↑この結果のドライブ数が表示され、
MsgBox fso.aaaa
↑この実行時にエラーになります。これは、当たり前
つまり、プロシジャーの実行はされていることになります。

【67281】Re:例3
発言  ichinose  - 10/11/19(金) 20:30 -

引用なし
パスワード
   例3
シートの保護という機能がありますよね?
この機能、Excel2000と2002では、大きく仕様が変っていますよね?
Excel2002からは、保護する内容が細かく指定できるようになっています。
よって、Protectメソッドのオプションも2002から、増えています。

新規ブックにて、

標準モジュールに
Sub test5()
  Dim sht As Worksheet
  Set sht = ActiveSheet
  If Application.Version = "9.0" Then
    sht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
  Else
    sht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
    , AllowFormattingCells:=True, AllowFormattingColumns:=True, _
    AllowFormattingRows:=True
  End If
End Sub

このtest5をExcel2000で実行すると、

sht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
  , AllowFormattingCells:=True, AllowFormattingColumns:=True, _
   AllowFormattingRows:=True
↑ここがコンパイルエラーになります。

が、
Sub test5()
  Dim sht As Worksheet
  Set sht = ActiveSheet
  If Application.Version = "9.0" Then
    sht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
  Else
    'sht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
    , AllowFormattingCells:=True, AllowFormattingColumns:=True, _
    AllowFormattingRows:=True  コメント化しておくこと
  End If
End Sub
Sub test6()
  Dim sht As Object
  Set sht = ActiveSheet
  If Application.Version = "9.0" Then
    sht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
  Else
    sht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
    , AllowFormattingCells:=True, AllowFormattingColumns:=True, _
    AllowFormattingRows:=True
  End If
End Sub


test6を実行すると、コンパイルエラーにはならず、
正常にシートが保護されます。
(因みにExcel2002では、どちらも正常に作動します)

これらの例から見ると、Object型変数を使った操作でいけそうですが・・・。

ちょっと前に目安箱に

www.vbalab.net/vbaqa/c-board.cgi?cmd=ntr;tree=247;id=FAQ

こんな投稿したことがありました
(あらっ、ちょっと前って一年も前ジャン)。
関連性があるので確認してみてください。

以上です。

【67282】追伸
発言  ichinose  - 10/11/19(金) 21:02 -

引用なし
パスワード
   留意点

Object型変数の使用で一つだけ気になったこと。

オブジェクト内に Friendキーワードが使ったメソッドがあると、
Object型変数からは、呼び出せませんねえ・・・・。
この場合、CallByName関数でも駄目です。

【67286】Re:バージョンの違いによる引数変化の対応
発言  熊谷隆史  - 10/11/20(土) 8:24 -

引用なし
パスワード
   ▼neptune さん:
> で、その後はVBAは進化してないと思います。つまりVBA6のまんま。
> ここまでは多分間違ってはないと思います。
Office 2010からWin64も考慮していますので、
VBA7になっています。
ht tp://msdn.microsoft.com/ja-jp/library/ee691831.aspx

【67297】Re:バージョンの違いによる引数変化の対応
お礼  neptune  - 10/11/21(日) 21:12 -

引用なし
パスワード
   ▼熊谷隆史 さん:
ご指摘ありがとうございます。
おかげで間違いのままにせずに済みました。
64bit対応ですか。VBAもまだ進化していたんですね。

>▼neptune さん:
>> で、その後はVBAは進化してないと思います。つまりVBA6のまんま。
>> ここまでは多分間違ってはないと思います。
>Office 2010からWin64も考慮していますので、
>VBA7になっています。
>ht tp://msdn.microsoft.com/ja-jp/library/ee691831.aspx

【67302】Re:追伸
お礼  ぴのぽ  - 10/11/22(月) 14:51 -

引用なし
パスワード
   お返事遅れて申し訳ございません。

Objectの使い方が悪かったのでしょうか。以前やったときはコンパイルエラーになってしまいました。

CreateByNameは、引数に与えた名前のメソッドと引数で間接的にメソッドを呼び出しているという機能だと受け止めているのですが、Objectを使った処理(遅延バインディングと言うのでしょうか…)がまだよく理解していないため、やり方等々が曖昧でとりあえずCreateByNameで行っております。

例示されたサンプルを元にObjectの方ももう少し調べていこうと思います。
丁寧なサンプルありがとうございました。
またObjectに関して不明点があればご質問させていただきます。

2553 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free