VB6でのExcel.Applicationの定義?

解決


よっしー  2009-08-01 17:11:46  No: 142313

次々に質問で申し訳ないのですが。

VB2008で動く物をVB6に移植しようと思いますが、
Dim xlApp As Excel.Application
でユーザー定義型は定義されていませんとのエラー出力があります。

'Excel本体表示、マクロ実行、Excel本体残し
Private Sub Command1_Click()
        Dim er_f As Boolean
        Call Excel_exe(False, False, "c:\test.xls", "auto_open", False, er_f)
        MsgBox (er_f)
End Sub
'Excel本体非表示、マクロ実行、Excel本体消去
Private Sub Command2_Click()
        Dim er_f As Boolean
        Call Excel_exe(True, False, "c:\test.xls", "auto_open", True, er_f)
        MsgBox (er_f)
End Sub

    'Excelを起動指定して起動する。
    '****************
    'hide=true Excel本体を隠すか?
    'err_f=true Excelの警告、メッセージ表示?
    'file_pn= "c:\tmp\*.xls 開くファイルパスとファイル名
    'exe_mn= "auto_open" 実行するマクロ名
    'Excel_end=true 最後にExcel本体を終了するか?
    'exe_err=true 実行結果のエラー返し
    Private Sub Excel_exe(ByVal hide_f As Boolean, ByVal err_f As Boolean, ByVal file_pn As String, ByVal exe_mn As String, ByVal Excel_end As Boolean, ByVal exe_err As Boolean)
        Dim xlApp As Excel.Application
        Dim xlbook As Excel.Workbook
        On Error GoTo Er1

        ' Excelのインスタンス作成
        xlApp = CreateObject("Excel.Application")

        ' Excelの表示有無
        If hide_f = True Then
            xlApp.Visible = False
        Else
            xlApp.Visible = True
        End If

        ' マクロの警告やメッセージを表示するか?
        If err_f = True Then
            xlApp.DisplayAlerts = True
        Else
            xlApp.DisplayAlerts = False
        End If

        ' 指定したExcelファイルを開く
        If file_pn <> "" Then
            xlbook = xlApp.Workbooks.Open(file_pn)
        Else
            'Excelを通常起動する。
            xlbook = CType(xlApp.Workbooks.Add, Excel.Workbook)
        End If

        ' マクロの実行
        If exe_mn <> "" Then
            xlApp.Run (exe_mn)
        End If

        ' Excelの終了
        If Excel_end = True Then
            xlApp.Quit()
        End If

        ' オブジェクトを解放
        xlbook = Nothing
        xlApp = Nothing
        exe_err = False
        Exit Sub
Er1:
        ' エラーメッセージを表示
        exe_err = True
    End Sub


そふと99  2009-08-01 20:58:50  No: 142314

メニューバーの
  プロジェクト(P)
    参照設定(N)

Microsoft Excel XXX ObjectLirary
にチェックを入れる
ない場合はあきらめる。


しんご  2009-08-01 21:38:54  No: 142315

> ユーザー定義型は定義されていません

そふと99さんの書き込みのとおりです。
参照設定行ってください。

ちなみに、VB6で動かすには
このエラー以外にもエラーだらけです。

> xlApp = CreateObject("Excel.Application")
Set xlApp = CreateObject("Excel.Application")  が正解

> xlbook = xlApp.Workbooks.Open(file_pn)
こちらも Set が必要

> xlbook = CType(xlApp.Workbooks.Add, Excel.Workbook)
この「CType」って何ですか?VB6にはないと思います。

> xlApp.Quit()
xlApp.Quit が正しい

オブジェクトを解放する際も Set が必要です。

下記サイトに、VB6でエクセルを扱う方法が書かれています。
ご参考まで。

ttp://hanatyan.sakura.ne.jp/vbhlp/excelframe.htm

エクセルとは関係ない部分ですが、もう少しプログラムを
改良できると思います。

たとえば、

If hide_f = True Then
   xlApp.Visible = False
Else
   xlApp.Visible = True
End If

としていますが、
xlApp.Visible = Not hide_f
とすればいいのではないでしょうか?

あと引数を ByVal にする必要はないのでは?
ByRef と ByVal の違いはわかりますか?


魔界の仮面弁士  2009-08-02 01:14:29  No: 142316

それ、参考にしている .NET 用のコードに問題がありますよ。

動く事は動くと思いますが、VB6 向けコードを、そのまま VB.NET に翻訳しただけのような
作りになっていて、VB.NET として使うには、いろいろと問題のあるコードになっています。
(オブジェクトの解放処理が無く、単に Nothing を代入しているだけとか、
 参照設定しているのに CreateObject しているとか。細かいところでは、
 CType よりも DirectCast を使う方が望ましい、とか。)

まぁ、それゆえに VB6 に翻訳しやすいコードである、とも言えますが。

>> Dim xlApp As Excel.Application
>> でユーザー定義型は定義されていませんとのエラー出力があります。
この場合は、その変数定義を As Object にするだけで OK です。
ついでに、モジュールの先頭に「Option Explicit」も入れておきましょう。

一応、VB6 で Excel を参照設定すれば "As Excel.Application" を利用できますし、
参照設定した方が本来は望ましいです。

しかし参照設定すると、「親オブジェクトを指定せずに、シートやセルを利用する」といった
“誤ったコード”を書いたときに、2 回目以降の Excel 操作が失敗するようになったり、
Excel が終了しなくなるといった、気づきにくい問題を抱える可能性があります。
http://homepage1.nifty.com/rucio/main/technique/teq_15.htm

参照設定しなかった場合は、そのような親オブジェクトを指定しないコードは
「変数が宣言されていません」のエラーとなるため、“誤ったコード”が
混入することを防げます。
なので VB6 から操作するのであれば、まずは参照設定無しで始めるというのも一つの手です。
(.NET の場合は、逆に参照設定しない事によるデメリットの方が大きいのですが…)

>> xlbook = CType(xlApp.Workbooks.Add, Excel.Workbook)
> この「CType」って何ですか?VB6にはないと思います。
型変換のための関数です。

VB6 の場合、オブジェクトをキャストする場合には、目的の型の
変数を用意して、そこに代入する必要があります。
http://support.microsoft.com/kb/168830/ja

つまりこの場合、変数のキャストを行う場合には
  Dim xlBook As Excel.Workbook
に対して、
  Set xlBook = xlApp.Workbooks.Add()
というコードを書けばよいことになります。型変換の関数は不要です。

> あと引数を ByVal にする必要はないのでは?
> ByRef と ByVal の違いはわかりますか?
それは逆でしょう。
ByVal で良い——というよりも、ByValにするべき——だと思いますよ。
(ByVal / ByRef を省略した場合、VB6 では ByRef、VB.NET では ByVal の意味になります)

ByVal の場合、プロシージャ内で引数が指す物が入れ替わらない事が保証されます。
今回のようなパターンでは、ByRef にするメリットは殆どありません。

VB6 で ByRef を「使わなければならない」パターンとは、
  ・ByVal では渡せない型を引数にする場合(ユーザー定義型)
  ・プロシージャ内で引数を書き換える必要がある場合
  ・ByVal として宣言することが許可されていないイベントプロシージャを利用する場合
などに限られます。
それ以外の場合、VB6 で意図的に ByVal/ByRef を記述するのであれば、極力、ByVal を選択するべきかと。


しんご  2009-08-02 09:56:37  No: 142317

魔界の仮面弁士さま

訂正ありがとうございます。
知識が豊富で尊敬しております。

> ByVal の場合、プロシージャ内で引数が指す物が
> 入れ替わらない事が保証されます。
> 今回のようなパターンでは、ByRef にするメリットは殆どありません。

たしかにそうなのですが、このプログラムは
VB.net から VB に変換済みのコードではないのですね。

>VB2008で動く物をVB6に移植しようと思いますが、
>Dim xlApp As Excel.Application
>でユーザー定義型は定義されていませんとのエラー出力があります。

とあったので、既にVB6に変換済みでVB6で動かしたと思ってました。
なので「ん?」と思ったわけです。

意図的に書くのであれば ByVal を選択すべきと私も思いますが、
このプログラムでは意図的に書いたとは思えなかったので・・・


よっしー  2009-08-02 15:58:16  No: 142318

皆さんご回答頂きましたが私にはこの件VB6に変換するのは
無理と判断し、再勉強してみますので、この場は一応
かってとは思いますが、解決とさせて頂きます。
再度別に質問させてもらいます。
大変ご迷惑をおかけしますが、その時は宜しく願います。


よっしー  2009-08-02 15:59:28  No: 142319

すみません仮解決です。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加