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
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
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
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というレコードセットのデータを直接シート状に出力するメソッドがありますので、
それを利用して貼り付けます。
どの手法をとるにしても細かいところは出てくるものです。躓かない限りは気づかず済むことも多いのでACCESSで済むうちは「できればOK」みたいなところもありますね
(逆に躓くと、細かいところに気づくまで深みにハマるわけですが)
>> 2でGoogle検索のURLを出していますが、その検索結果でやり方を公開しているサイトが見つかります
色々とありがとうございます。奥の深いことがあり、勉強になります。
作成してますファイルは私を含めた社内の担当しか使いませんので Q_Dummy は非表示にする必要はありません。
対象フォームは何かフィルターをしなければ対象項目がリスト表示されない形です(例えば発注先を選択等)
まず細かい処理はせずにhatenaさんのコードを使い試してみました。問題なく動作しました(フォームと同じフィルターでエクスポート出来ています)こんなに簡潔に出来て感激です。
無知ついでにお聞きしたいのですが(全然理解出来ておらず恥ずかしい限りですが)、今回はSQLだけを使い実行出来ましたが、DAOでレコードセットにして処理する方法もあるのでしょうか?
レコードセットは漠然としたイメージしかなく、どういう時に使うのかなと思ってましたので。ネットの情報見てもSQL、DAOの関係がつかめないもので(初級レベルの事ですみません)
あと[フィルターの実行]ボタンでした。
ハンドルネームを入力し忘れました、失礼。
・String 型の変数の初期値は Null ではなく空文字列である。
・String 型の変数に Null を代入することは出来ない。
・したがって、上記の条件式の結果は常に True となる。
・フォームの Filter プロパティに何らかの Where 条件が設定されていても、
FilterOn プロパティが False である状態であればフォームフィルターは
適用されず、レコードソースの全てのレコードが表示される。
・[ホーム]タブ上の[フォームの実行]ボタンや、フォームの移動ボタン上の
[フィルター適用/フィルター処理なし]ボタンをユーザーがクリックすることによって
フォームフィルターが解除され得ることを想定するのであれば、Filter プロパティの
値が空文字列ではなく、かつ FilterOn プロパティの値が True である場合のみ、
SQL に WHERE 句を付加するようにすることが望ましい。
(でないと、フォーム上に全てのレコードが表示されているのに対し、
クエリ側ではレコードの抽出が行われているという矛盾した状態となり得る)
Docmdは非同期処理なので、前のレコード移動が終わる前に次のレコード移動でエラーになっている可能性があるのでは?
Form.Filter プロパティ (Access) | Microsoft Learn
補足
フォームのFilterプロパティに設定する条件式は、クエリのWHERE句以降に設定する条件式と同じものです。よって、クエリのWHERE句にFilterプロパティの値を設定することはできます。
今回のようにエクスポートするときに、
一時的に使うクエリを事前に作成しておいて、エクスポート時にそれを書き換えて利用する、
という運用は特に問題ないと私は考えてきます。
名前付けに関してはQ_Dummyでは何者か分からないというのなら、分かる名前にすればいいでしょう。「エクセルエクスポート用一時クエリ」とか。
ユーザーに触られるのが不安なら、「隠しオブジェクト」にしておけばナビゲーションウインドウでは非表示にできます。
別の方法としては、エクスポートするたびにクエリを新規作成(CreateQueryDef)して、エクスポート後削除するということも考えられますが、
Accessでオブジェクトの作成、削除を繰り返すことは、ファイルサイズが増えたり、破損の危険性が高くなるので、私としては避けたいと思っています。
ACCESSのクエリは実体はテキストデータです
クエリのビューの切り替えでSQLビューを表示すればSQL記述を確認できます
SQLビューであればテキストのコピペができるのでいろいろ捗ります
クエリデザインで作成したものをSQL表示してみる、または、SQLコピペしたものをクエリデザインで確認するなどすると理解が進むと思います(クエリを保存すると自動整形される/されてしまう点には注意が必要です)
hatenaさん記述の
Me.Filter
は抽出条件入力用フォームのフィルター(文字列)をフォームのモジュール内から参照しています流れ的には、フォームのフィルター文字列を使って新たなSQL構文を作成し、それを基に新たなクエリを作成しています。Excelへのエクスポートの前に毎回クエリを作り直すイメージですね
クエリそのものが
Me.Filter
を扱えるわけではありませんQ_Dummy
に関する注意点としては、ぱっと見それが何者か分からないということです。また、条件抽出用のフォームと依存関係にあるのに、ナビゲーションウインドウから直接開けてしまう(クエリを開いた場合のデータの正しさが保証されていない)という問題がありますACCESSで作るシステムにどこまで要求するか?仕様と開発コストからどの程度まで妥協するかというところですが、開発(プログラミング)の原則から見ると推奨されない構造を取ることになります
プロパティやコマンド、関数などはヘルプや公式ドキュメントで確認するようにするとヒントがいろいろ見つかります。
Form.Filter プロパティ (Access) | Microsoft Learn
hirotonさん・hatenaさんありがとうございます。大変参考になります。
クエリもフォームやレポート同様にMe.Filter条件が可能とは知りませんでした。
いつもクエリばかりでSQL記述した事がありませんが、内容を勉強してある程度理解したら試してみます。
それで分からない事がでてきたらまた投稿致しますので宜しくお願いします。
その要件なら、ダミーのクエリを作成しておいて、そのSQLを書き換えてエクスポートするという方法が簡単ではないでしょうか。
下記で、フィールドを選択してエクスポートするという方法を紹介しています。
それの応用でできるでしょう。
テーブルのフィールドを指定してエクスポート - hatena chips
Q_Dummy という名前のクエリを作成しておきます。上書きしますので中身はなんでもいいです。
いろいろ方法はあると思いますが、とりあえずこれ
https://www.google.com/search?q=access フォーム フィルター excel出力
できる、できないで言えば出来ます
ACCESS クエリの抽出条件でフォームを参照させる方法(VBAコード公開)(たすけてACCESS さん)
※ページタイトルそのまま記載していますが、リンク先でVBAは使われていません
全てのフィルターを必ず設定するならフォームのコントロールを参照する式を設定すれば問題ありません。そうでない場合は、「固定で組み込んでしまった抽出処理をどのように回避するか?」という複雑な問題が発生します
Excelへの出力が目的なら
・フォームで抽出を行い、フォームのレコードを直接出力する(VBA)
・複雑なクエリを組んで抽出条件の有無にどうにか対応する
・毎回クエリそのものを作り直す(VBA)
どれかの手法になると思います
VBAのコードはコピペして使えるものも検索で見つかります。用法に合うならそれが一番簡単だと思います。手直しが必要な場合は、規模・能力によってVBAまたは、複雑なクエリどちらかでしょう
クエリそのものを作り直すのは「できる」というだけの話でそこまで大事にすることではないでしょう
hatena様
ご教授ありがとうございます
試してみたら出来ました。 また何かあったらよろしくお願いいたします
Valueプロパティに今日の日付を代入すればいいでしょう。
使用している activeX カレンダーは Microsoftカレンダーコントロール11.0になります
問題が起きるテーブルを、xmlでエクスポートして、
再度インポートしたテーブルを使用したらエラーが起きなくなりました。
なにか、確認できないゴミみたいなものが入っていたのでしょう。
バージョンは、2016の64ビットのままなので、
accessのバグみたいなもんですね。
エラー番号 2147467259は、テーブルの入れ替えで解決できました。
hatena様
試してみました。
うまく動きました。本当にありがとうございました。
hatena様
早速のご回答ありがとうございます。
50音選択ボタン(オプションボタン)の設計は下記にサンプルがあります。
オプショングループで50音選択 - hatena chips
オプショングループで50音選択 改良版 - hatena chips
オプショングループで50音選択 高速版 - hatena chips
これらはフォームのFilterに条件を設定して絞り込むサンプルですが、
これをコンボボックスの値集合ソースを書き換えるように書き換えればいいでしょう。
りんご様
ありがとうございました。参考サイトで出来ました☺
hiroton様
わざわざご返信いただきましてありがとうございました
この方式を試したのですが各ボックスに書式設定をしても
表示上はその見え方をするのですが データは**//**が残ってしまい
上手く扱えなかったです
いろいろご教授頂きましてありがとうございます
また何かありましたらよろしくお願いいたします
りんご様
お返事ありがとうございます。
PDFを単体で開く場合、自動的に希望の倍率で表示されました。
りんご様の質問に対してはYESです。
自分が混乱しておりました。誠にありがとうございました。
タイトルにあるけど本当に「カレンダーコント―ロール11.0」?
とっくに廃れて解説も見つからないようなコントロールだけど
https://oshiete.goo.ne.jp/qa/2156743.html
https://tsware.jp/study/vol16/vbabegin_34.htm
より高度な使い方を模索しているページしか見つからなかったけど、「クリック時」イベントがあるのでそれを使えば「カレンダーコントロールで指定した値」を取り出せます
イベントで値が使えるならそれをそのまま「ボックス」に入力するようにすればいいです
「ボックス」がナニモノか分からないけど、非連結のテキストボックスなら日付データそのまま入れて書式の設定でそれぞれ「yyyy」「mm」「dd」って設定しておけばいいんじゃないですかね
ただ表示するだけでいいのであれば、3回別々にデータを入力することもないので
「(月)」と「(日)」はコントロールソースを
=[(年)]
としてもいいと思います下記を参考に実現できませんか?
T’sWare #550日付データを年・月・日別々のテキストボックスに表示する方法
ご解説ありがとうございます。
値を代入した瞬間にレコード位置が変わっていたのですか。
Sortプロパティも良く気を付けて使わなければならないですね。
Sort設定した瞬間だけ並び替えが行われるのものかと。
いえ、「[残業区分]の値に 3 を代入( 1 から 3 に変更)した瞬間」です。
Update メソッドが呼び出されるより先に並べ替えが行われています。
(イミディエイトウィンドウへの出力結果)
以上のように、AbsolutePosition プロパティの値の変化からも今回の現象の原因を説明することができます。
sk様、Hiroton様、Hatena様
皆様、この度は真摯なご回答誠にありがとうございました。
問題解決することができました!
個々に手動で変更しなくても、自動的に希望の倍率(環境設定の値)で表示されるようになったのかしら?YESの場合、目的(PDF表示倍率変更)は達成されたのだから、Access云々の手段は不要になったはずですが。手段と目的がすり替わっていませんか?
sk様
ご提示の
「Sort プロパティを使用せず Open メソッドの呼び出し時に「 ORDER BY 句付きの SELECT 文」を渡すこと」
で出来ました!
debug.printでも95が表示されますし、処理も残業区分が4になってます。
ちなみにレコードの並び替えが必要な理由は、途中略の部分にありますので(おそらく並び替えが必要な処理)
やはり、残業管理ID=130で残業区分=3にして、rs.updateで並び替えが行われているということですかね。
もっとも、「[日付]の値が休日に該当する場合は[残業区分]の値を書き換える」という処理だけに着目するのであれば、そもそもレコードを並べ替えること自体が不要であるとも言えますが。
hatena様
イミディエイトでは何も出力されませんでした。
デバッグコードの位置を以下にすると、
以下のように出ます。
84 2024/04/20
130 2024/04/21
85 2024/04/21
ならば考えられる原因は 1 つだけです。
[残業管理ID]の値が 130 であるレコードの[残業区分]の値に 3 を代入( 1 から 3 に変更)した瞬間に、そのレコードが 2 番目から 3 番目のレコードに、[残業管理ID]の値が 95 である([残業区分]の値が 2 である)レコードが 3 番目から 2 番目のレコードになった(レコードセット内での絶対位置が入れ替わった)からです。
【 3 を代入する直前の状態】
【 3 を代入した直後の状態】
順番が入れ替わってもその時点でのカレントレコードは[残業管理ID]の値が 130 であるレコードのままなので、その後 MoveNext メソッドを呼び出せばその次( 4 番目)のレコードは[残業管理ID]の値が 85 であるレコードとなります。
回避手段としては、Sort プロパティを使用せず Open メソッドの呼び出し時に「 ORDER BY 句付きの SELECT 文」を渡すことが挙げられます。
コードには問題がなさそうなので、データの問題の可能性が大です。
このような場合は、こちらにはデータがないのでそちらでデバッグ作業をするしかなです。
デバッグの方法についてはすでにリンクが紹介されていますので、そちらを参照してもらうとして、
とりあえず下記のデバッグコードを埋め込んで、イミディエイトの出力結果を確認してみてください。
皆様
早急なご回答誠にありがとうございます。
試したところPDFファイルを単独で開くと同じ倍率で表示するようになりました。
しかし、adobe PDF reader ActiveXを貼り付けると
「OLEが見つかりません」とメッセージが表示され、動作しません。
調べたところAdobe AcrobatがないとOLEインストールできないようです。
次にX-Change Viewerでも同じことを試しました。
同様にPDFファイルから開くと同じ倍率になりますが、
貼り付けても反映されませんでした。
Adobe Acrobatを持っていないため購入するか、
X-Changeを調査していく方向になりそうです。
もしほかに方法がございましたらお教えいただけませんでしょうか。
どうぞよろしくお願いいたします。
84、130、85しか表示されていませんでした。
書き換えたコードは途中略なしです。
Hiroton様
Debug.Print rs!残業管理ID を実行しましたが、95が表示されていませんでした。
sk様
追加のコードについては、投稿時に端折っただけです。
ご提示の1~5の選択肢については3だと思われます。
下記のコードに書き換えて実行してみました。
それでも同じく残業管理ID 95の残業区分が4にならずに2のままでした。
他の残業区分IDは残業区分が3になっています。
PDFを常に同じ倍率で表示する! 毎回、表示を変更する手間を省く時短方法
adobe reader の環境設定で初期倍率を設定しないの?