Microsoft Access 掲示板

クラスモジュールについて

17 コメント
views
4 フォロー

お世話になります。

以前、hatena様が回答された掲示板を見て、クラスモジュールを勉強しています。

紹介されたURLは、
https://codezine.jp/article/detail/504

です。

ACCESSのクエリを、Excelに保存するというコードです。

標準モジュール

Sub レコード全体をExcelに転送する()
    Dim Qex As New clsTrans
    
    With Qex
        .QryName = "商品区分別商品リスト"
        .SaveBookName = "C:\Users\Desktop\20211201\Desktop\QryData.xlsx"
        .ToExcel
    End With
    
    Set Qex = Nothing
End Sub

クラスモジュール

Option Compare Database

'プロパティ設定
Public QryName As String        '開くクエリ名の設定
Public SaveBookName As String  '保存するブック名の設定

'オブジェクト変数
Dim QryBook As Excel.Workbook

Public Sub ToExcel()
    Dim ex As Excel.Application
    
    Set ex = CreateObject("excel.Application")
    ex.Visible = True
        
    DoCmd.OpenQuery QryName, , acReadOnly
    DoCmd.RunCommand acCmdOutputToExcel
    DoCmd.RunCommand acCmdClose
    
    If SaveBookName <> "" Then
        ex.ActiveWorkbook.SaveAs SaveBookName
    Else
        MsgBox "保存するブック名をSaveBookNameプロパティで設定してください"
    End If
    
    Set ex = Nothing
End Sub
Public Sub Excel_Close()
    'excelを終了する
    'ex.Quit
    
    Set QryBook = Nothing
    Set ex = Nothing
End Sub

このコードを実行すると、

オブジェクト変数、または、with ,ブロック変数が設定されていません。

または、指定のレコードを表示形式で保存できません。⇒ここのエラー文言は忘れましたけど、このようなエラーです。
↑ここのエラー内容も、掲示板で、hatena様の回答を確認したのですが、正解にたどりつけませんでした。

どのように修正するのか、お手数ですが、ご教示をお願いします。

申し訳ありません。

hideki
作成: 2021/12/10 (金) 15:01:46
通報 ...
1

このコードを実行すると、

どのコードですか。
Excel_Close() のことですか。
これは、クラスモジュール内に記述しているのですか。

だとしたら、ex変数はモジュールレベルで宣言する必要があります。

Option Compare Database

'プロパティ設定
Public QryName As String        '開くクエリ名の設定
Public SaveBookName As String  '保存するブック名の設定

'オブジェクト変数
Dim QryBook As Excel.Workbook
Dim ex As Excel.Application 'ここで宣言

Public Sub ToExcel()
'    Dim ex As Excel.Application これは削除
    
    Set ex = CreateObject("excel.Application")
    ex.Visible = True
        
    DoCmd.OpenQuery QryName, , acReadOnly
    DoCmd.RunCommand acCmdOutputToExcel
    DoCmd.RunCommand acCmdClose
    
    If SaveBookName <> "" Then
        ex.ActiveWorkbook.SaveAs SaveBookName
    Else
        MsgBox "保存するブック名をSaveBookNameプロパティで設定してください"
    End If
    
'    Set ex = Nothing これも削除
End Sub

Public Sub Excel_Close()
    If ex Is Nothing Then Exit Sub 'これを追加 

    'excelを終了する
    ex.Quit
    
    Set QryBook = Nothing
    Set ex = Nothing
End Sub
2
hideki 2021/12/11 (土) 23:53:10 7cbc1@96514

hatena様 

エラーの場所の記載をしなくて申し訳ありません。

.ToExcel⇒ここで、デバックが発生します。

,,,jp

 If SaveBookName <> "" Then
        ex.ActiveWorkbook.SaveAs SaveBookName
    Else
        MsgBox "保存するブック名をSaveBookNameプロパティで設定してください"
    End If

,,,

F8で実行していくと、ここの部分でエラーが発生します。

3
りんご 2021/12/12 (日) 13:49:32 c564b@0e907 >> 2

 とりあえず、これくらい試しましたか?

 If SaveBookName <> "" Then
        ex.ActiveWorkbook.SaveAs SaveBookName
     Debug.Print SaveBookName
     MsgBox SaveBookName
    Else
        MsgBox "保存するブック名をSaveBookNameプロパティで設定してください"
    End If
4

提示のコード、試してみましたが、いろいろおかしいですね。
参考にした下記の記事、

Access 2003 VBAではじめるクラス入門 (1/4):CodeZine(コードジン)

Access 2003とあるようにかなり古い記事のようです。
私自身、この記事を紹介した記憶がないのですが、どの掲示板で紹介しましたか。
そのURLを提示してもらえますか。

とりあえず、ACCESSのクエリを、Excelに保存するだけなら、クラスモジュールを使う必然性はないです。
DoCmd.TransferSpreadsheetメソッドで簡単にできますので。

DoCmd.TransferSpreadsheet acExport, _
                          "商品区分別商品リスト", "C:\Users\Desktop\20211201\Desktop\QryData.xlsx"

クラスモジュールの勉強なら、他にもっと適切なものがありそうです。

5
hideki 2021/12/13 (月) 21:47:02 7cbc1@96514

リンク

この記事です。

多分、丁寧な回答を読んでいるとhatena様かと思います。

紹介されたURLのExcelは、リンク切れでした。

hatena様のブログは全部読みました。
時間のある時は、分からなくても読んでいます。

ACCESSに関しての、クラスモジュールは、DAOや、ADOのものが少しNETにあるだけでした。

このyahoo知恵袋で、hatena様が、紹介されているなら、間違いない教材と思って勉強してました。

ご提示していただいた、コードは知っています。

単純にクラスモジュールで記載したらどうなるのかと思い、ご無礼を承知で、質問しました。

12

そのリンク先、確かに私の回答ですね。
「ざっと検索してみました」といっているように中身までは検証していません。

その時は紹介しましたが、今、サンプルファイルをダウンロードしてみましたが、2010以降のバージョンではサポートされていないデータアクセスページを使用していて、動作を確認できないものなので今から学習するサンプルとしては適切でないです。記事内のコードだけでは完結しないのでサンプルで確認する必要もありますので。

なぜ、クラスモジュールの勉強しようと思い立ったのか分かりませんが、Accessはデータベースとしての強力な機能を持っていますので、クラスモジュールを使う場面はほとんどありません。
かなり、大きなシステムを構築するなら活用できる場面があるかも知れませんが、このような質問で出てくるようスキルレベルでは必要な場面に出会うとこもないし、使いこなせないと思います。

私自身も、テーブル数、フォーム数、レポート数がそれぞれ2桁以上の大がかりてシステムを作成しましたが、クラスモジュールは使ってません。

6
hideki 2021/12/13 (月) 21:48:40 7cbc1@96514

りんご様

回答ありがとうございます。
イミディエイトウィンドウには、何も表示されませんでした。

7
りんご 2021/12/13 (月) 22:02:15 c564b@0e907 >> 6

イミディエイトウィンドウには、何も表示されませんでした。
えっとですね、貴方はそれをどう評価・考察しましたか?

8
hideki 2021/12/13 (月) 23:21:52 7cbc1@96514

りんご様

QryData.xlsxが、おかしいと思いました。

9
りんご 2021/12/13 (月) 23:51:50 c564b@0e907 >> 8

 SaveBookNameを使ってあれこれやりたいと書いているのに、肝心の中身が表示されないってどういう事でしょう?
 >> 8
 QryData.xlsxって、急に何処から出してきたの?

10
hideki 2021/12/14 (火) 01:10:30 7cbc1@96514

"C:\Users\Desktop\20211201\Desktop\QryData.xlsx"です。
指定したデータを、出力できないというような、エラーがでました。
ACCESS2003でしたし、Excelの保存形式も違っていたので。

11
りんご 2021/12/14 (火) 02:05:45 c564b@0e907

>> 3
>> 7>> 9>> 10
ごめんなさい、私の勘違いと力不足がありました。
もしかしたら、こちらが参考になるかもしれません。

ACCESSからのExcel操作について|teratail
ACCESSからExcel操作のVBAは初めてで躓いております。どうかよろしくお願い致します。 ◆やりたいことACCESSのフォームからチェックボックスで選択した取引先データをCopyFromRecordsetで書き出し、横長のクエリを切り分けExcel上で見やすい帳票に加工したい ◆できている
teratail[テラテイル]

Application.Workbooks.Add.SaveAs “ほにゃらら”みたいな感じになるのかしら?

13
hideki 2021/12/14 (火) 10:45:18 7cbc1@2aadf

りんご様
ありがとうございます。
参考にさせていただきます。

14

ToExcelでなぜエラーが出るかを解説(コメント)しておきますと。

Public Sub ToExcel()
    Dim ex As Excel.Application

    Set ex = CreateObject("excel.Application")
    ex.Visible = True
    '↑ここでエクセルアプリケーションが新規に開く
    'ただし、ブックは開いてないので空っぽの状態。
        
    DoCmd.OpenQuery QryName, , acReadOnly
    DoCmd.RunCommand acCmdOutputToExcel
    '↑エクセルへクエリデータを出力するが、上で開いているエクセルではなく
    '別に新規のエクセルを開いてそこに出力する。
    DoCmd.RunCommand acCmdClose
    
    If SaveBookName <> "" Then
        ex.ActiveWorkbook.SaveAs SaveBookName
        'exは最初に開いた空っぽのエクセルで、ブック自体存在しないので、エラーになる
    Else
        MsgBox "保存するブック名をSaveBookNameプロパティで設定してください"
    End If
    
    Set ex = Nothing
End Sub

対処法としては、CreateObjectで新規エクセルを開くのではなく、
GetObjectで開いているエクセルを取得して操作することになると思います。

前にも言いましたが、DoCmd.TransferSpreadsheetメソッドで1行でできることをわさわざクラスモジュールですることはないし、上記のような間違いもあるし、古い記事なので、クラスモジュールの学習サンプルとしては適切ではないです。

15
hideki 2021/12/14 (火) 11:23:49 7cbc1@2aadf

hatena様

クラスモジュールを勉強しようと、思ったのは、オブジェクト指向という言葉に出会ってからです。
今思えば、ACCESSが、まったく理解できていないとき、yahooの知恵袋で、本当に丁寧に回答してくれたのが、hatena様でした。

hatena様は、どのようにスキルを習得したのか?
きっと、hatena様なら、色々な技で、スマートな短いコードで、やりたいと事を実現できるんだろうなと、
今も、そう考えながら、コードを書いています。
クラスモジュールを理解できたら、きっと、また、違った世界が見えるかもしれないと思い、勉強しようと思いました。
クラスモジュールは、今の私には、難しく、yahooの知恵袋で、クラスモジュール、hatenaで検索したら、HITしたので、その回答を、何度も読んで、ブログも読んで、紹介していただいたリンク先のブログも読んでいました。

また、わかないところがあれば、図々しく、質問させていただきます。

また、この掲示板で、回答してただいた、hatena様、りんご様をはじめ、全ての方に、感謝申し上げます。
ありがとうございました。

17
りんご 2021/12/14 (火) 22:46:09 c564b@0e907 >> 15

 オブジェクト指向の流行はピークを過ぎたんじゃないでしょうか?得意分野と伸び代の目処がついたという意味で。少なくとも、データベースの設計にはイマイチみたいですよ。

16
hideki 2021/12/14 (火) 11:34:18 7cbc1@96514

hatena様
詳しい回答ありがとうございました。