Microsoft Access 掲示板

views
4 フォロー
6,278 件中 361 から 400 までを表示しています。
12

DoCmd.TransferSpreadsheet というのはAccessの機能、
リボンメニューのエクスポートあるいは右クリックのエクスポートの機能を、VBAから実行しています。

SQLというのは、テーブルデータの抽出、集計、並べ替え、更新・・・・・などのデータ操作をするためのデータベース用言語、
それを視覚的に扱えるようにしたのがAccessのクエリ。SQLビューにすればSQLコードをみることができます。

DAOというのは、データベースのデータ操作を、VBAなどのプログラミング言語から操作できるようにしたライブラリー。
Accessのテーブルだけでなく、他のデータベースのデータや、CSVやエクセルのデータもデータベースとして扱えます。

AccessのテーブルデータをDAOでエクセルに出力するサンプルコードは、
ちょっと古いですが、下記にあります。

access技メモ(2003-2007)詳細

こちらのコードでは、OpenRecordset でテーブルを開いていますが、SQLで開くこともできますので、

Set rs = db.OpenRecordset("SELECT * FROM テーブル名 Where " & Me.Filter & ";")

とすればフォームと同じレコードセットを取得できます。

エクセルはCopyFromRecordsetというレコードセットのデータを直接シート状に出力するメソッドがありますので、
それを利用して貼り付けます。

11
hiroton 2024/05/09 (木) 14:09:50 7f972@f966d

どの手法をとるにしても細かいところは出てくるものです。躓かない限りは気づかず済むことも多いのでACCESSで済むうちは「できればOK」みたいなところもありますね
(逆に躓くと、細かいところに気づくまで深みにハマるわけですが)

DAOでレコードセットにして処理する方法もあるのでしょうか?

>> 2でGoogle検索のURLを出していますが、その検索結果でやり方を公開しているサイトが見つかります

10

色々とありがとうございます。奥の深いことがあり、勉強になります。
作成してますファイルは私を含めた社内の担当しか使いませんので Q_Dummy は非表示にする必要はありません。
対象フォームは何かフィルターをしなければ対象項目がリスト表示されない形です(例えば発注先を選択等)
まず細かい処理はせずにhatenaさんのコードを使い試してみました。問題なく動作しました(フォームと同じフィルターでエクスポート出来ています)こんなに簡潔に出来て感激です。
無知ついでにお聞きしたいのですが(全然理解出来ておらず恥ずかしい限りですが)、今回はSQLだけを使い実行出来ましたが、DAOでレコードセットにして処理する方法もあるのでしょうか?
レコードセットは漠然としたイメージしかなく、どういう時に使うのかなと思ってましたので。ネットの情報見てもSQL、DAOの関係がつかめないもので(初級レベルの事ですみません)

9

[ホーム]タブ上の[フォームの実行]ボタン

あと[フィルターの実行]ボタンでした。

8

ハンドルネームを入力し忘れました、失礼。

7
名前なし 2024/05/09 (木) 10:59:59 b4927@fc3ed

Dim strFilter As String

・String 型の変数の初期値は Null ではなく空文字列である。

・String 型の変数に Null を代入することは出来ない。

If Not IsNull(strFilter) Then

・したがって、上記の条件式の結果は常に True となる。

   If strFilter <> "" Then
      Me.FilterOn = True
   Else
      Me.FilterOn = False
   End If

・フォームの Filter プロパティに何らかの Where 条件が設定されていても、
 FilterOn プロパティが False である状態であればフォームフィルターは
 適用されず、レコードソースの全てのレコードが表示される。

Dim strSQL As String
strSQL = "SELECT * FROM テーブル名 Where " & Me.Filter & ";"
CurrentDb.QueryDefs("Q_Dummy").SQL = strSQL

・[ホーム]タブ上の[フォームの実行]ボタンや、フォームの移動ボタン上の
 [フィルター適用/フィルター処理なし]ボタンをユーザーがクリックすることによって
 フォームフィルターが解除され得ることを想定するのであれば、Filter プロパティの
 値が空文字列ではなく、かつ FilterOn プロパティの値が True である場合のみ、
 SQL に WHERE 句を付加するようにすることが望ましい。
 (でないと、フォーム上に全てのレコードが表示されているのに対し、
 クエリ側ではレコードの抽出が行われているという矛盾した状態となり得る)

Dim strSQL As String   
strSQL = "SELECT * FROM [テーブル名]"
If Me.Filter <> "" And Me.FilterOn = True Then
    strSQL = strSQL & " WHERE " & Me.Filter
End If
strSQL = strSQL & ";"
CurrentDb.QueryDefs("Q_Dummy").SQL = strSQL
2
ssassakki 2024/05/09 (木) 10:32:19 27741@c61b7

Docmdは非同期処理なので、前のレコード移動が終わる前に次のレコード移動でエラーになっている可能性があるのでは?

6

Form.Filter プロパティ (Access) | Microsoft Learn
補足
フォームのFilterプロパティに設定する条件式は、クエリのWHERE句以降に設定する条件式と同じものです。よって、クエリのWHERE句にFilterプロパティの値を設定することはできます。


今回のようにエクスポートするときに、
一時的に使うクエリを事前に作成しておいて、エクスポート時にそれを書き換えて利用する、
という運用は特に問題ないと私は考えてきます。

名前付けに関してはQ_Dummyでは何者か分からないというのなら、分かる名前にすればいいでしょう。「エクセルエクスポート用一時クエリ」とか。

ユーザーに触られるのが不安なら、「隠しオブジェクト」にしておけばナビゲーションウインドウでは非表示にできます。

別の方法としては、エクスポートするたびにクエリを新規作成(CreateQueryDef)して、エクスポート後削除するということも考えられますが、
Accessでオブジェクトの作成、削除を繰り返すことは、ファイルサイズが増えたり、破損の危険性が高くなるので、私としては避けたいと思っています。

5
hiroton 2024/05/08 (水) 09:54:06 d241b@f966d

ACCESSのクエリは実体はテキストデータです
クエリのビューの切り替えでSQLビューを表示すればSQL記述を確認できます
SQLビューであればテキストのコピペができるのでいろいろ捗ります

クエリデザインで作成したものをSQL表示してみる、または、SQLコピペしたものをクエリデザインで確認するなどすると理解が進むと思います(クエリを保存すると自動整形される/されてしまう点には注意が必要です)


hatenaさん記述のMe.Filterは抽出条件入力用フォームのフィルター(文字列)をフォームのモジュール内から参照しています
流れ的には、フォームのフィルター文字列を使って新たなSQL構文を作成し、それを基に新たなクエリを作成しています。Excelへのエクスポートの前に毎回クエリを作り直すイメージですね
クエリそのものがMe.Filterを扱えるわけではありません


Q_Dummyに関する注意点としては、ぱっと見それが何者か分からないということです。また、条件抽出用のフォームと依存関係にあるのに、ナビゲーションウインドウから直接開けてしまう(クエリを開いた場合のデータの正しさが保証されていない)という問題があります

ACCESSで作るシステムにどこまで要求するか?仕様と開発コストからどの程度まで妥協するかというところですが、開発(プログラミング)の原則から見ると推奨されない構造を取ることになります

4

プロパティやコマンド、関数などはヘルプや公式ドキュメントで確認するようにするとヒントがいろいろ見つかります。

Form.Filter プロパティ (Access) | Microsoft Learn

注釈

Filter プロパティの設定値は、WHERE 句から WHERE を省いた文字列式です。

3

hirotonさん・hatenaさんありがとうございます。大変参考になります。
クエリもフォームやレポート同様にMe.Filter条件が可能とは知りませんでした。
いつもクエリばかりでSQL記述した事がありませんが、内容を勉強してある程度理解したら試してみます。
それで分からない事がでてきたらまた投稿致しますので宜しくお願いします。

2
hatena 2024/05/07 (火) 18:14:35 修正

その要件なら、ダミーのクエリを作成しておいて、そのSQLを書き換えてエクスポートするという方法が簡単ではないでしょうか。

下記で、フィールドを選択してエクスポートするという方法を紹介しています。
それの応用でできるでしょう。

テーブルのフィールドを指定してエクスポート - hatena chips

Q_Dummy という名前のクエリを作成しておきます。上書きしますので中身はなんでもいいです。

Private Sub cmdExport_Click()
    Dim strFileName As String
    strFileName = "C:\Test\Test.xlsx"
    Dim strSQL As String   
    strSQL = "SELECT * FROM テーブル名 Where " & Me.Filter & ";" 
    CurrentDb.QueryDefs("Q_Dummy").SQL = strSQL
    DoCmd.TransferSpreadsheet acExport, , "Q_Dummy", strFileName, True
End Sub
1
hiroton 2024/05/07 (火) 17:00:55 d915e@f966d

いろいろ方法はあると思いますが、とりあえずこれ

https://www.google.com/search?q=access フォーム フィルター excel出力


フォームのフィルターをクエリに反映可能?

できる、できないで言えば出来ます

ACCESS クエリの抽出条件でフォームを参照させる方法(VBAコード公開)(たすけてACCESS さん)
※ページタイトルそのまま記載していますが、リンク先でVBAは使われていません

全てのフィルターを必ず設定するならフォームのコントロールを参照する式を設定すれば問題ありません。そうでない場合は、「固定で組み込んでしまった抽出処理をどのように回避するか?」という複雑な問題が発生します

Excelへの出力が目的なら
・フォームで抽出を行い、フォームのレコードを直接出力する(VBA)
・複雑なクエリを組んで抽出条件の有無にどうにか対応する
・毎回クエリそのものを作り直す(VBA)

どれかの手法になると思います

VBAのコードはコピペして使えるものも検索で見つかります。用法に合うならそれが一番簡単だと思います。手直しが必要な場合は、規模・能力によってVBAまたは、複雑なクエリどちらかでしょう
クエリそのものを作り直すのは「できる」というだけの話でそこまで大事にすることではないでしょう

3
ゆきぷりん 2024/05/05 (日) 21:20:05 947bd@b9243

hatena様
ご教授ありがとうございます
試してみたら出来ました。 また何かあったらよろしくお願いいたします

2

Valueプロパティに今日の日付を代入すればいいでしょう。

Me.カレンダーコントロール名.Value = Date
1
ゆきぷりん 2024/05/05 (日) 10:38:15 947bd@b9243

使用している activeX カレンダーは Microsoftカレンダーコントロール11.0になります

1
タークン 2024/05/04 (土) 14:30:17 7a0a1@2705a

問題が起きるテーブルを、xmlでエクスポートして、
再度インポートしたテーブルを使用したらエラーが起きなくなりました。

なにか、確認できないゴミみたいなものが入っていたのでしょう。
バージョンは、2016の64ビットのままなので、
accessのバグみたいなもんですね。

エラー番号 2147467259は、テーブルの入れ替えで解決できました。

3
solamomo 2024/05/02 (木) 17:11:26 087ff@0185a

hatena様
試してみました。
うまく動きました。本当にありがとうございました。

2
solamomo 2024/05/02 (木) 16:52:35 087ff@0185a

hatena様
早速のご回答ありがとうございます。

1

50音選択ボタン(オプションボタン)の設計は下記にサンプルがあります。

オプショングループで50音選択 - hatena chips

オプショングループで50音選択 改良版 - hatena chips

オプショングループで50音選択 高速版 - hatena chips

これらはフォームのFilterに条件を設定して絞り込むサンプルですが、
これをコンボボックスの値集合ソースを書き換えるように書き換えればいいでしょう。

3
ゆきぷりん 2024/05/02 (木) 15:51:01 947bd@b9243

りんご様
ありがとうございました。参考サイトで出来ました

hiroton様 
わざわざご返信いただきましてありがとうございました
この方式を試したのですが各ボックスに書式設定をしても
表示上はその見え方をするのですが データは**//**が残ってしまい
上手く扱えなかったです

いろいろご教授頂きましてありがとうございます
また何かありましたらよろしくお願いいたします

5
MochaShima 2024/05/02 (木) 15:44:43 d2d23@fb7d0

りんご様

お返事ありがとうございます。
PDFを単体で開く場合、自動的に希望の倍率で表示されました。
りんご様の質問に対してはYESです。

自分が混乱しておりました。誠にありがとうございました。

2
hiroton 2024/05/02 (木) 14:40:12 修正 8d44d@f966d

タイトルにあるけど本当に「カレンダーコント―ロール11.0」?
とっくに廃れて解説も見つからないようなコントロールだけど

https://oshiete.goo.ne.jp/qa/2156743.html
https://tsware.jp/study/vol16/vbabegin_34.htm

より高度な使い方を模索しているページしか見つからなかったけど、「クリック時」イベントがあるのでそれを使えば「カレンダーコントロールで指定した値」を取り出せます

イベントで値が使えるならそれをそのまま「ボックス」に入力するようにすればいいです

Private Sub Calendar0_Click()
    Me![(年)] = Me!Calendar0
    Me![(月)] = Me!Calendar0
    Me![(日)] = Me!Calendar0
End Sub

「ボックス」がナニモノか分からないけど、非連結のテキストボックスなら日付データそのまま入れて書式の設定でそれぞれ「yyyy」「mm」「dd」って設定しておけばいいんじゃないですかね
ただ表示するだけでいいのであれば、3回別々にデータを入力することもないので
「(月)」と「(日)」はコントロールソースを=[(年)]としてもいいと思います

16

ご解説ありがとうございます。
値を代入した瞬間にレコード位置が変わっていたのですか。

Sortプロパティも良く気を付けて使わなければならないですね。
Sort設定した瞬間だけ並び替えが行われるのものかと。

15

やはり、残業管理ID=130で残業区分=3にして、rs.updateで並び替えが行われているということですかね。

いえ、「[残業区分]の値に 3 を代入( 1 から 3 に変更)した瞬間」です。
Update メソッドが呼び出されるより先に並べ替えが行われています。

Debug.Print "【値の代入前】"
Debug.Print "[残業管理ID]の値: " & rs![残業管理ID].Value
Debug.Print "[残業区分]の値: " & rs![残業区分].Value
Debug.Print "レコードセット内の絶対位置: " & rs.AbsolutePosition
rs!残業区分.Value = 3
Debug.Print "【値の代入後】"
Debug.Print "[残業管理ID]の値: " & rs![残業管理ID].Value
Debug.Print "[残業区分]の値: " & rs![残業区分].Value
Debug.Print "レコードセット内の絶対位置: " & rs.AbsolutePosition
rs.Update

(イミディエイトウィンドウへの出力結果)

【値の代入前】
[残業管理ID]の値: 130
[残業区分]の値: 1
レコードセット内の絶対位置: 2
【値の代入後】
[残業管理ID]の値: 130
[残業区分]の値: 3
レコードセット内の絶対位置: 3

以上のように、AbsolutePosition プロパティの値の変化からも今回の現象の原因を説明することができます。

14
あん 2024/05/02 (木) 11:45:51 b41ab@001b1

sk様、Hiroton様、Hatena様
皆様、この度は真摯なご回答誠にありがとうございました。
問題解決することができました!

4
りんご 2024/05/02 (木) 11:42:33 修正 935bc@0e907

試したところPDFファイルを単独で開くと同じ倍率で表示するようになりました。

 個々に手動で変更しなくても、自動的に希望の倍率(環境設定の値)で表示されるようになったのかしら?YESの場合、目的(PDF表示倍率変更)は達成されたのだから、Access云々の手段は不要になったはずですが。手段と目的がすり替わっていませんか?

13
あん 2024/05/02 (木) 11:39:49 b41ab@001b1

sk様
ご提示の
「Sort プロパティを使用せず Open メソッドの呼び出し時に「 ORDER BY 句付きの SELECT 文」を渡すこと」
で出来ました!

debug.printでも95が表示されますし、処理も残業区分が4になってます。

ちなみにレコードの並び替えが必要な理由は、途中略の部分にありますので(おそらく並び替えが必要な処理)

やはり、残業管理ID=130で残業区分=3にして、rs.updateで並び替えが行われているということですかね。

12

もっとも、「[日付]の値が休日に該当する場合は[残業区分]の値を書き換える」という処理だけに着目するのであれば、そもそもレコードを並べ替えること自体が不要であるとも言えますが。

11

hatena様
イミディエイトでは何も出力されませんでした。

デバッグコードの位置を以下にすると、

Do Until rs.EOF

    Debug.Print rs!残業管理ID, rs!日付

        If rs!残業区分 = 1 Then

以下のように出ます。
 84           2024/04/20
 130          2024/04/21
 85           2024/04/21

10

ならば考えられる原因は 1 つだけです。

rs.Sort = "日付 ASC, 担当者ID ASC, 残業区分 ASC"

rs!残業区分 = 3

[残業管理ID]の値が 130 であるレコードの[残業区分]の値に 3 を代入( 1 から 3 に変更)した瞬間に、そのレコードが 2 番目から 3 番目のレコードに、[残業管理ID]の値が 95 である([残業区分]の値が 2 である)レコードが 3 番目から 2 番目のレコードになった(レコードセット内での絶対位置が入れ替わった)からです。

【 3 を代入する直前の状態】
画像1

【 3 を代入した直後の状態】
画像2

順番が入れ替わってもその時点でのカレントレコードは[残業管理ID]の値が 130 であるレコードのままなので、その後 MoveNext メソッドを呼び出せばその次( 4 番目)のレコードは[残業管理ID]の値が 85 であるレコードとなります。

回避手段としては、Sort プロパティを使用せず Open メソッドの呼び出し時に「 ORDER BY 句付きの SELECT 文」を渡すことが挙げられます。

rs.Open "SELECT * FROM [tbl残業管理] ORDER BY [日付] ASC, [担当者ID] ASC, [残業区分] ASC", cn, adOpenKeyset, adLockOptimistic
9

コードには問題がなさそうなので、データの問題の可能性が大です。

このような場合は、こちらにはデータがないのでそちらでデバッグ作業をするしかなです。
デバッグの方法についてはすでにリンクが紹介されていますので、そちらを参照してもらうとして、
とりあえず下記のデバッグコードを埋め込んで、イミディエイトの出力結果を確認してみてください。

'前略

        ElseIf rs!残業区分 = 2 Then
            Debug.Print rs!残業管理ID, rs!日付     'デバッグコード
            If DCount("休日", "tbl休日", "休日 = #" & rs!日付 & "#") > 0 Then

'後略
3
MochaShima 2024/05/02 (木) 10:24:02 d2d23@fb7d0

皆様

早急なご回答誠にありがとうございます。
試したところPDFファイルを単独で開くと同じ倍率で表示するようになりました。
しかし、adobe PDF reader ActiveXを貼り付けると
「OLEが見つかりません」とメッセージが表示され、動作しません。
調べたところAdobe AcrobatがないとOLEインストールできないようです。

次にX-Change Viewerでも同じことを試しました。
同様にPDFファイルから開くと同じ倍率になりますが、
貼り付けても反映されませんでした。

Adobe Acrobatを持っていないため購入するか、
X-Changeを調査していく方向になりそうです。
もしほかに方法がございましたらお教えいただけませんでしょうか。
どうぞよろしくお願いいたします。

8

84、130、85しか表示されていませんでした。

7

書き換えたコードは途中略なしです。

6
あん 2024/05/02 (木) 10:12:49 b41ab@001b1

Hiroton様

Debug.Print rs!残業管理ID を実行しましたが、95が表示されていませんでした。

5

sk様
追加のコードについては、投稿時に端折っただけです。

ご提示の1~5の選択肢については3だと思われます。

下記のコードに書き換えて実行してみました。
それでも同じく残業管理ID 95の残業区分が4にならずに2のままでした。
他の残業区分IDは残業区分が3になっています。

    Dim cn As New ADODB.Connection
    Dim rs As New ADODB.Recordset

    Set cn = CurrentProject.Connection
    
    rs.CursorLocation = adUseClient
    rs.Open "tbl残業管理", cn, adOpenKeyset, adLockOptimistic


    rs.Sort = "日付 ASC, 担当者ID ASC, 残業区分 ASC"
    rs.MoveFirst
    
    
    Do Until rs.EOF
    
        If rs!残業区分 = 1 Then
        
            If DCount("休日", "tbl休日", "休日 = #" & rs!日付 & "#") > 0 Then
            
                rs!残業区分 = 3
                rs.Update
                
            End If

    
        ElseIf rs!残業区分 = 2 Then
        
            If DCount("休日", "tbl休日", "休日 = #" & rs!日付 & "#") > 0 Then
            
                rs!残業区分 = 4
                rs.Update
            
            End If

        End If
        
        rs.MoveNext
          
    Loop


    rs.Sort = ""

    rs.Close: Set rs = Nothing
    cn.Close: Set cn = Nothing