'Microsoft Office XX.X Access Database Engine Object Library に参照設定必用
Private Sub エクスポートボタン_Click()
Dim db As DAO.Database
Dim qd As DAO.QueryDef
Dim strFilter As String
Dim strSQL As String
'フィルターが設定されてなかったら実行しない
If Me.Filter = "" Or Me.Filter = "False" Then Exit Sub
'クエリのSQLにWHERE句を追加
Set qd = db.QueryDefs("クエリ1")
strSQL = Replace(qd.SQL, ";", "")
qd.SQL = strSQL & " WHERE " & Me.Filter & ";"
'テキストエクスポート
DoCmd.TransferText acExportDelim, "エクスポート定義1", "クエリ1", _
"C:\Test\Output.txt"
'クエリのSQLを元に戻す
qd.SQL = strSQL & ";"
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case vbKeyLeft, vbKeyUp, vbKeyRight, vbKeyDown
KeyCode = 0
End Select
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If (Shift And acShiftMask) > 0 Then
Select Case KeyCode
Case vbKeyLeft To vbKeyDown
KeyCode = 0
End Select
End If
End Sub
下記でどうでしょう。
複数バージョンをインストールしているとか、特別なことをしてなければ、excel.exeはたいていパスが通っているので、下記でも大丈夫かと。
ちょっと上手く動くか分かりませんが。
Shell """" & 変数A & """" & """" 変数B & 変数C & """"
もしくは
Shell """" & 変数A & """""" 変数B & 変数C & """"
hatenaさん、りんごさん、アドバイスありがとうございます。
まず、オプショングループを設置してでのクエリを開くは無事作成することができました。
今まではクエリの抽出指定する時などは非連結のテキストボックスやプルダウンリストを使っていましたが、オプショングループは使用者にとって視覚的にもわかりやすいですね。
今までの知識だと今回のようなケースはあらかじめ年別、月別、日別、全期間でグループ化しておいたクエリを作って、フォームにそれぞれを開くボタンを設置していましたがとてもシンプルになりました。
結果は今までの方法でも得られたと思いますが、クエリやフォーム上のボタンなど乱立もせず、ボタンのイベントも複数個所メンテナンスする必要がなくなるのでしっかり身に着けたいと思います。ありがとうございました。
Dim WshObj As Object
Dim UN As String
Set WshObj = CreateObject("WScript.Network")
UN = WshObj.UserName
をいれて UsernameをUNにしたら できました
回答をしてくれた方ありがとうございました
質問では「任意のフォルダにエクセルで出力したい」とのことですが、この「任意のフォルダー」とは何でしょうか。
具体的に説明してください。
ログインユーザー名は
Environ("USERNAME")
で取得できますが、それは任意のフォルダーとは言わないと思います。
①と②を試したところUserNameが取得できていませんでした
表示させるとC:\Users\○○○リスト2022****.xlsx となってしまいます
どうすれば UserNameをうまく取得できるのでしょうか
>> 1
Aテーブル.詳細フィールドとBテーブル.内容フィールドを内部結合する、これでも差し障りないと思いますか?
>> 3
横にそれます。あえて、年月別のテーブルに持つ、という選択肢もあるようです。組み方はちょっと分かりませんが。
横からすみません。>> 4の "\○○○リスト"でも駄目でしたか?
しっかり把握していませんが、取り敢えず、下記をやっておくと解決に近づくかもしれません。
①変数UserNameとFormat関数の部分を手打ちに置き換える。結果、問題なく開ける?
②変更UserNameとFormat関数の中身をMsgboxやDebug.Printで表示。結果、①の手打ちと同じ?
strPath = "C:\Users\" & UserName & "○○○リスト" & Format(Now(), "yyyymmdd") & ".xlsx"
としましたが
今度は実行時エラー’2220’
ファイルC:\Users\" & UserName & "○○○リスト2022****.xlsx"を開くことができませんと表示されます
上記でダメなら下記も試してみてください。
の部分ですが、ファイルパスに拡張子をつけてみてください。
Excel出力のVBAを以下のように書きました
Private Sub Excel出力_Click()
'変数宣言
Dim strPath As String
'Excelエクスポート先のファイルパス
strPath = "C:\Users\" & UserName & "○○○リスト" & Format(Now(), "yyyymmdd")
'Excelファイルの出力
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "○○○リスト出力", strPath, False
'Excelファイルをエクスポートした旨を通知する。
MsgBox "○○○リストを出力しました。" & vbCrLf & "C:\Users\" & UserName & "\OUT\", vbInformation
End Sub
を実行すると
実行時エラー’3051’
ファイル’C¥Users¥○○○リスト2022****’を開くか、書き込むことができませんでした。ほかのユーザーが排他的に開いているか、データーの表示と書き込みを行う権限がありません。
とメッセージがでてしまいます
どうしtら解消できるでしょうか
よろしくお願いします
下記の手順で簡単にオプショングループを設置できます。
コントロールウィザードがONの状態でフォーム上にオプショングループを配置します。
ウィザードで、ラベル名を下記のように設定すれば、あとは、次へボタンをクリックしていけば完成します。
あとは、クエリを開くコマンドボタンを配置すればいいでしょう。
早速上記のフィールドを作成して試してみました!
まだフォームでの切り替え制御までは手を付けられていませんが、既にクエリ実行時に表示されるダイアログで1~4を指定すればグループの間隔を1つのクエリで制御できました!基幹システムに備わっている集計機能の煩わしさをこれでフォローできてしまいそうです…勉強になりました。
下記のようなフィールドを作成してそれでグループ化すれば一つのクエリで可能です。
[年別:1, 月別:2, 日別:3, 全期間:4]というパラメータが出ますので1~4の数値を入力することでグループ間隔を指定できます。
フォームにオプショングループを配置しておいて、それを参照するようにすれば、フォームでオプションを選択すればグループ間隔を切り替えて表示できます。
早速のご回答ありがとうございました。
上記方法ですぐに求めていることが実現できました、助かりました。
追記に関してですが、かえって混乱をさせてしまいました。解決済みです。
集計するのに年単位、月単位で見れるようにしたいというのが希望でしたが、それに関しては2つのクエリを作成して年別クエリには年だけのフィールド、月別クエリには年、月を用意しておけば良いとわかっていました。
月別売上実績
年 月 顧客名 売上額 粗利額 粗利率
2022 4 A株式会社 10000 8000 80%
2022 5 A株式会社 20000 8000 40%
2022 6 A株式会社 30000 8000 27%
2022 4 有限会社B 5000 4000 80%
2022 5 有限会社B 6000 3000 50%
2022 6 有限会社B 7000 2000 29%
年別売上実績
年 顧客名 売上額 粗利額 粗利率
2022 A株式会社 60000 24000 40%
2022 有限会社B 18000 9000 50%
すごく初歩的なお話になってしまうのですが、こういったデータ分析をするのにAccessクエリを使うことは過去にもよくありましたが上記例のように年別、月別、日別、全期間などグループ化する重点をどこかに置くかの違いだけで似たようなクエリが続出していきます。クエリが増えていくこと自体は業務で必要なことなので構わないのですが、これってスマートなやり方なの?と思うときがあります。
追記に関しては、現状の 年:Year([売上計上日)]と月:Month([売上計上日]) の設定では希望と異なるのですか。
具体的にどのような出力になってほしいのでしょうか。
希望の出力を例示してもらえますか。
クエリのデザインビューで下記のように設定してください。
設定ダイアログで、ファイル形式で、拡張子が .xls のものを選択してませんか。
Excel Workbook(.xlsx) に変更して試してみてください。
ありがとうございます
できました
クエリを新規作成して、AテーブルとBテーブルを追加します。
[詳細]フィールドの抽出条件に下記のように設定してください。
これでご希望の結果になると思います。
SQLビューなら下記になります。
自己解決ですみません。
.Sheets(1).Cells(2, 1) = PONUM
.Sheets(1).Cells(2, 2) = PRNUM
右辺と左辺が逆でした。
PONUM = .Sheets(1).Cells(2, 1)
PRNUM = .Sheets(1).Cells(2, 2)
でできるようになりました。
お騒がせしてすみませんでした。
みなさまありがとうございます!
今、hirotonさんに教えて頂いた魔法使いの開発工房さんのやつをやってみて、できました!
今後データ件数はかなり増えることが予想されるので、りんごさん、hatenaさんのご提案もこれから試してみます!
こちらのサイトは本当に勉強になります!
ありがとうございました!
あ!よくみたら、りんごさんの式とは違いましたね。
ただ、この方法はインデックスが無効になるので、データ数が多いときは、避けたい方法ですね。
(フィールドが関数内に入っているので)
抽出条件でインデックスが無効になる場合 - hatena chips
しっかり試してないけど、入力制限を外して、フォーカス喪失時に
Undoが駄目ならsetfocusでフォーカスを戻す。(10未満になるまでフォーカス喪失出来ないようにするとか)
エラーメッセは、適当なオブジェクトででっち上げて非表示から表示にするとか。ー
定型入力を使用してデータ入力形式を制御する
例えば
CCCCCCCCCC
と指定すれば10文字までになります数字に限定するなら
9999999999
など魔法使いの開発工房さんところのはフィールドで
True
/False
を作る手法なのでNullなレコードも抽出対象ですよ(抽出条件はTrue
だけ)方法としては、主に下記の2つになります。
クエリで抽出条件を設定する。そのクエリをフォームのレコードソースにして、再クエリで抽出条件を反映させる。
このクエリをDoCmd.TransferText メソッドでエクスポートする。
フォームのFilterプロパティに抽出条件を設定して、フィルタリングする。
VBAでクエリのWHERE句をフォームのFilterプロパティで書き換える。
このクエリをDoCmd.TransferText メソッドでエクスポートする。
前者は、シンプルですが対象フィールドが複数になると条件が複雑になりがちです。(PCTipsさんのリンク先参照)
魔法使いの開発工房さんの方法(=りんごさんの回答)は、割とシンプルですが、Null値のレコードは抽出されません。(それでも問題ない、あるいはNull値はないないら、これでいいでしょう。)現状は、フォームのFilterプロパティに抽出条件を設定しているのて、2.の方法のサンプルを提示しておきます。
クエリ1 はWHERE句のないシンプルなもの。
事前にクエリ1でエクスポートして、エクスポート定義を作成しておく。
エクスポート定義で、タブ区切り、やデータ型などを設定する。
Like IIf(IsNull([Forms]![txt出力]![コンボボックスA]),"*",[Forms]![txt出力]![コンボボックスA])
試してないから失敗したら、ごめんなさい。
よくある手法
【Access】複数テキストボックスが空の場合は無視して値がある時だけ抽出できるクエリってできないの?(PCTipsさん)
汎用性の高い手法
MS-Access97超入門>絞込みの仕組みを作る(魔法使いの開発工房さん)
VBAで動的にクエリを作るとか、フォームのデータを直接テキストファイルとして吐き出す(VBA)とかもありますね
VBAで動的にクエリを作るならできます
フォームのフィルターは以下をボタンに埋め込んでいます。
Private Sub 絞込みボタン_Click()
Dim strFilter As String
'[材質・メーカー]の条件の指定
If Nz(Me![コンボボックスA], "") <> "" Then
strFilter = strFilter & _
" AND (CSVエクスポート_クエリ.[材質] Like '" & Replace(Me![コンボボックスA], "'", "''", , , vbBinaryCompare) & "')"
End If
'[発注先]の条件の指定
If Nz(Me![コンボボックスB], "") <> "" Then
strFilter = strFilter & _
" AND (CSVエクスポート_クエリ.[仕入先] Like '" & Replace(Me![コンボボックスB], "'", "''", , , vbBinaryCompare) & "')"
End If
'先頭の" AND "を取り除く
strFilter = Mid(strFilter, 6)
'フィルター条件がひとつでもあったら
If strFilter <> Null Or strFilter <> "" Then
'フィルター条件の設定
Me.Filter = strFilter
'フィルターの実行 (もしくは解除)
Me.FilterOn = (strFilter <> "")
'フィルター条件がなにもなかったら、レコードを全件非表示にする
Else
Me.Filter = "False"
Me.FilterOn = True
End If
End Sub
これと同じことを、全く同じフィールドを持つ別のクエリを作り、抽出条件に書こうとしています。その後クエリを実行してtxtファイルにエクスポートしようとしています。
よろしくお願いします。
フォームでのフィルタリングはどのようにしているのでしょうか。
レコードソースのクエリに抽出条件を設定している。
あるいは、
フォームのフィルター機能を使っている。
これは、どのように実現しているのでしょうか。
それとも、この設定方が分からないということでしょうか。
ありがとうございます。
申し訳ございません。
原因はフォームモジュールのレコードソースに設定したクエリの作り方でした。
エラーメッセージは【このレコードセットは更新できません】でした。
クエリを修正したらご指摘の内容で解決しました。
お門違いな質問で申し訳ございませんでした。
通常は、
でOKです。
Formatは ”0501” という文字列を返します。
それを数値型フィールドに代入すれば、自動で数値型に変換されますので。
ということで、下記の情報を提示してください。
エラーメッセージを提示してください。
このコードをどこに記述していますか。(標準モジュール? フォームモジュール?)
コードの一部ではなく、 プロシージャ全体を提示してください。
ご回答ありがとうございます!
DCount("*","TESTテーブル","ID <=" & [ID] & "and F3='" & [F3] & "' and F4 =#" & [F4] & "#")
でいけました!すごいです!
いつもありがとうございます!
「キーボードイベント取得」を「はい」にして
KeyCode As Integer
なので、KeyCode=Null
だとエラーになります。KeyCode = 0
でなかったことになります。フォームの「キーボードイベント取得」を「はい」に設定。
フォームのキークリック時のイベントプロシージャに下記を記述。
上手くいけばいいのですが。
DCount("*","テーブル","ID<=" & [ID] & "and F3='" & [F3] & "' and F4 =#" & [F4] "#")