SELECT
T_入出庫一覧.区分,
[移動日] - Day([移動日]) + 1 AS 移動月,
Sum(IIf(
[区分ID] = 1,
[合計]
)) AS 入庫数,
Sum(IIf(
[区分ID] = 2,
[合計]
)) AS 出庫数,
T_区分マスター.手数料単価,
Sum([手数料単価] * [合計]) AS 手数料
T_区分マスター.区分ID,
FROM
T_入出庫一覧
INNER JOIN
T_区分マスター
ON T_入出庫一覧.区分 = T_区分マスター.区分
GROUP BY
T_入出庫一覧.区分,
[移動日] - Day([移動日]) + 1,
T_区分マスター.手数料単価,
T_区分マスター.区分ID
ORDER BY
[移動日] - Day([移動日]) + 1,
T_区分マスター.区分ID
;
上記クエリによるレポート出力用の基礎データ例
レポートのモジュール
Option Compare Database
Option Explicit
Dim No As Long
Dim 保管月 As Date
Dim 保管個数 As Long
Private Sub Report_Load()
保管月 = DateAdd("M", -1, Me!移動月)
End Sub
Private Sub 移動月フッター_Format(Cancel As Integer, FormatCount As Integer)
No出力 Me!No_保管
'//補完用データ確保
保管月 = Me!移動月
保管個数 = Me!保管個数表示
End Sub
Private Sub 移動月ヘッダー_Format(Cancel As Integer, FormatCount As Integer)
If Me!移動月 = DateAdd("M", 1, 保管月) Then
Cancel = True
Exit Sub
End If
'//前のレコードが2月以上前なのでデータ補完
No出力 Me!No_補完
保管月 = DateAdd("M", 1, 保管月)
Me!移動月補完 = 保管月
Me!保管個数表示補完 = 保管個数
Me.NextRecord = False
End Sub
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
No出力 Me!No_入出庫
End Sub
Private Sub No出力(ctl As TextBox)
No = No + 1
ctl = No
End Sub
ありがとうございました。コードを下記で記述したのですが 『***大分類IDフィールドが見つかりません』のエラーが出ました。(大分類IDでグループ化してまして、それの3を非表示にしたい)
Private Sub グループフッター1_Format(Cancel As Integer, FormatCount As Integer)
Cancel = [大分類ID] = 3
End Sub
コードの記述が間違ってますでしょうか?
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
Dim j As Integer
Dim i As Integer
For j = 51 To 57
Me.DrawStyle = 0
Me.Line (Me("L" & j).Left, 0)-(Me("L" & j).Left, 144000)
Next
' For i = 2 To 12
' Me.DrawStyle = 2
' Me.Line (Me("L" & i).Left, 0)-(Me("L" & i).Left, 144000)
' Next
WordWrapOff Me.NAS用, Me.txtFld1
Me.NAS用.FELineBreak = False
Me.txtFld1.FELineBreak = False
End Sub
Dim i As Long
For i = 1 to 12
With Me.Controls("txt_" & i & "月")
.Visible = False
If Not IsNull(.Value) Then
Me.FontSize = .FontSize
Me.FontName = .FontName
Me.CurrentX = .Left + 26 '//26は位置調整のための数字
Me.CurrentY = (Me.Height / 2) - (Me.TextHeight(.Value) / 2)
Me.Print .Value
End If
End With
Next
Private Sub 詳細_Print(Cancel As Integer, PrintCount As Integer)
With Me.テキストボックス1
.Visible = False
Me.FontSize = .FontSize
Me.FontName = .FontName
Me.CurrentX = .Left
Me.CurrentY = (Me.Height / 2) - (Me.TextHeight(.Value) / 2)
Me.Print .Value
End With
End Sub
【現状のコード】
Private Sub 詳細_Print(Cancel As Integer, PrintCount As Integer)
With Me.請受金額月額
.Visible = False
.Format = "Currency"
Me.FontSize = .FontSize
Me.FontName = .FontName
Me.CurrentX = .Left
Me.CurrentY = (Me.Height / 2) - (Me.TextHeight(.Value) / 2)
Me.Print .Value
End With
If IsNull(Me.txt_1月) = False Then
If IsNull(Me.txt_1月) = True Then Me.txt_1月 = Me.txt_1月
With Me.txt_1月
.Visible = False
Me.FontSize = .FontSize
Me.FontName = .FontName
Me.CurrentX = .Left + 26 '//26は位置調整のための数字
Me.CurrentY = (Me.Height / 2) - (Me.TextHeight(.Value) / 2)
Me.Print .Value
End With
End If
End Sub
Dim h As Long
Private Sub Report_Load()
h = Me!Ctl1月.Height
End Sub
Private Sub 詳細_Print(Cancel As Integer, PrintCount As Integer)
Me!Ctl1月.TopMargin = (Me!自社用.Height - h) / 2
End Sub
hは固定値なので直接記述してもいいかなとも思います
例)
Private Sub 詳細_Print(Cancel As Integer, PrintCount As Integer)
Me!Ctl1月.TopMargin = (Me!自社用.Height - 270) / 2 '//270は元のMe!Ctl1月.height
End Sub
Private Sub 詳細_Print(Cancel As Integer, PrintCount As Integer)
With Me.テキストボックス1
.Visible = False
Me.FontSize = .FontSize
Me.FontName = .FontName
Me.CurrentX = .Left
Me.CurrentY = (Me.Height / 2) - (Me.TextHeight(.Value) / 2)
Me.Print .Value
End With
End Sub
その他
移動日/移動月については軽く触れていますが、そのほか、後の処理の(楽をしたい)都合で日付データとして各月の1日に統一したデータで扱っています
レポートの表示はテキストボックスの書式の設定(
YYYY年MM月
)で対応しています「抽出の最小日以前から保管個数がある場合」は考慮していません
その他、細かいところは適当なので(代替の背景色が有効のせいで微妙に表示がおかしいとか)そういう調整は必要です
こういう案件の場合、ワークテーブルを用意してゴリゴリしてからそれをレポートにとかってなるんですかねぇ
Noの連番取るのにVBA使わないとダメなの何か方法あるんじゃない?って思わなくもないけど、保管用のデータ作るとこと考えるとそっちがめちゃくちゃ遠回りになりそうだしなぁとか
「とりあえずやってみたらそれっぽくできたので公開してるだけ」なのでこういう手法どうなの?とかあればください
3.「存在しない月のデータ」をどう補完するか
「新しいデータを読み込んだ時、古いデータとの比較で月が離れていたら、データを挿入する」方法を取ります
「データ」はレポートのクエリを基に詳細セクションで読み込まれるので、「『移動月』でグループ化し、グループヘッダーを設置すると、『新しいデータと古いデータの間』」になります
このグループヘッダーを出力しなかったり、出力したり、たくさん出力するようにすれば、存在しないデータの補完ができます
移動月ヘッダーで表示する「区分」も「保管」のみなので、区分はラベルコントロールです
その他のテキストボックスはそれぞれ
です。存在しない月データの補完用のセクションなので全部「補完」とつけてるだけです
新しいレコードに移って捨てられてしまうデータをVBAで保存しておいて必要に応じて(非連結の)テキストボックスに設定、セクションの出力(繰り返し出力)をするとかそんな流れになっています
1.「保管」の累計個数をどう計算するか
入庫を足して在庫を減らして、それを積み立てれば累計(残在庫)です。ACCESSレポートではテンプレート的な用法があるのでそのまま使います
詳細セクションに「累計」テキストボックスを配置します
詳細セクションでデータを表示する必要はないので枠線だけ表示されるように調整しています。(非表示+枠線は別なコントロールでとかでもいいです)
「移動月」でグループ化して、フッターを配置し、「保管」行として使います
「保管」専用の行なので「区分」はラベルコントロールでそのまま「保管」を表示、その他必要なテキストボックスを配置します
2.「No」の連番をどう取得するか
「保管」データの累計計算のためにセクションを跨いでしまったのでVBAで計算・設定します
非連結のテキストボックスに、データが出力されるたび
+1
してデータを設定するだけです。「データが出力されるたび」がどんな時かきちんと把握しておく必要があります今回は適当に上から「No_補完」「No_入出庫」「No_保管」という名前にしました
出力のタイトルは「移動日」ですが、元データに「移動日」フィールドがあるので、データ段階では「移動月」の名前になっています。レポートに配置するラベルで「移動日」と表示すればいいと思います
この「移動月」でグループ化してヘッダー・フッターを設置します。デフォルトでは「グループヘッダー0」「グループフッター0」のような名前になっていますが、解説用にそれぞれ「移動月ヘッダー」「移動月フッター」と名前を変えています。
移動月ヘッダーの使い方は次での解説がメインですが、「No」表記が必要なのでここでの解説に「No_補完」が紛れ込んでいます
連番を付けるだけ、でいいのであればよくある手法があるんですが、その他の要求と組み合わせるとどうするといいのか悩みどころですね
適当に「2024年3月に400個出庫」のデータを加えたサンプル
hirotonは「簡単な手法」が思い浮かばなかったので覚悟してください
複雑な要件なので問題を分解します
1.「保管」の累計個数をどう計算するか
2.「No」の連番をどう取得するか
3.「存在しない月のデータ」をどう補完するか
回答としては一緒くたにやっていますが、どの問題を解決するためのものなのか考えながら見てください
レポートのレコードソースのクエリ
上記クエリによるレポート出力用の基礎データ例
レポートのモジュール
レポートのデザイン
両方あり得ます。
入庫・出庫が同一月に発生する場合、1行目入庫、2行目出庫、3行目保管になるようにしたいと考えています。
とりあえず確認
「入庫」「出庫」が同一月に発生することはありますか?その場合どのような表示になりますか?
「入庫」「出庫」が発生せず、「保管」だけが発生する月はありますか?
ありがとうございました。テキストボックス配置しましたら思い通りになりました。
ACCESSレポートは複雑でこんな方法は全く知りませんでした。
このグループだけレポートフッターに配置した他のデータから参照した値を含めた合計で表示したかったのです。
お世話になりました。
ありがとうございます!
非連結にすればよかったのですね。
回答頂けるまでにいろいろ試して、区分・商品1~4・合計・移動日・在庫移動日・発注日フィールドを持つtmpテーブルを作成し、こちらをレコードソースにしてフォーム作成しました!
結果が1件だけなら、いろいろ方法はありますが、
フォームの「在庫移動日」は非連結テキストボックスにしておきます。そうすれば入力可能になります。
レコードソースの集計クエリをもとに追加クエリを作成して、追加先は「T_入出庫状況」にします。
追加元と追加先の対応するフィールドを設定して、次に新規列に下記の設定をします。
SQLだと下記のようなになります。
フォーム上にコマンドボタンを配置して、そのクリック時にこの追加クエリを実行するようにすればいいでしょう。
グループフッターに大分類IDフィールドをテキストボックスとして配置してください。
大分類IDを表示したくない場合は「可視」を「いいえ」にします。
ありがとうございました。コードを下記で記述したのですが 『***大分類IDフィールドが見つかりません』のエラーが出ました。(大分類IDでグループ化してまして、それの3を非表示にしたい)
Private Sub グループフッター1_Format(Cancel As Integer, FormatCount As Integer)
Cancel = [大分類ID] = 3
End Sub
コードの記述が間違ってますでしょうか?
"T_発注書取込"テーブルの構成は
取込ID(オートナンバー)主キー
No(数値)
社名(短いテキスト)
〒(短いテキスト)
住所(短いテキスト)
TEL(短いテキスト)
商品1(短いテキスト)
商品2(短いテキスト)
商品3(短いテキスト)
商品4(短いテキスト)
発注日(日付/時刻)
発注日が複数日に渡ることはないので、グループ化で結果は1件だけになります。
この集計クエリの結果は1件だけですか。それとも複数件になりますか。
複数件の場合は、「在庫移動日」はすべて共通でいいのですか。それともレコード毎に異なるものを入力しますか。
それ以前に、現状のテーブルのフィールド構成はどうなってますか。
主キー設定も含めて提示してください。
はい、そうです。
とりあえず試してみてうまく行かない場合、質問してください。
フォーマット時イベントのCancel引数をTrueにすれば、そのセクションの出力を停止できます。
そのグループフッターの可視プロパティをフォーマット時イベントで制御すればいいかな?
※各名称は適切なモノに置き換えてください
また、
とし、詳細セクションのフォーマットイベントにあった罫線スタイルの指定をなくしたところうまくいきました。
(前はここがダブってしまっていて、線がきれいに点線になっていませんでした。)
大変失礼しました。
以上にて無事に担当に提出することが出来ました。
本当に長々とありがとうございました。
以下の様に修正しました。
通貨型、無事にできました!
ありがとうございます!!
失礼しました。
何かで作業途中になっていました…
不思議な現象ですねぇってことで書式「通貨」に設定したテキストボックスでテストをしてみました
結果
書式「通貨(Currency)」で使われる円記号はUnicodeのA5のようです。PrintメソッドがUnicodeに対応していないので文字化けするとかじゃないですかねぇ
文字コードの変換を入れてあげると円記号が表示できます
縦罫線に関しては前の質問でもページフォーマット時(Report_Page)でやればいいのでは?と回答してますが、うまくいかなかったんでしょうか?
ありがとうございます。
1.の通貨型なのですが
のような設定なのですが(日本円設定です)
になってしまいます。
他に設定しなくてはいけない部分があるのでしょうか?
2.の右揃えは出来ました。
ありがとうございます。
3.のこちらも出来ました。
ありがとうございます。
追加の質問で申し訳ないのですが
4.詳細セクションとグループフッターセクションのつなぎ目の部分で縦の罫線が微妙にずれます(画像の右縦線参照)
左位置は表示されている小数点第3位まで同じです。
しかし、設定上プロパティの左位置に数字を入力しても丸められているのか飛び飛びになるので実際にずれているのかもしれません。
これを画像の左縦線の様にまっすぐあわせるのは難しいのでしょうか?
5.画像の「6」が入力されている行が詳細セクションの(このページでの)最終行でその下がグループフッターセクションで作った空行なのですが、詳細セクションとグループフッターセクションの間に隙間ができてしまいます。
縦線の長さは全て一致して、セクションの高さも最小値(恐らく縦線の長さ+横下線の太さ分)になっていますがそれでも隙間が空きます。
また、縦線だけあえて少し長くしてみると
一番下の空白部分に線がはみ出します(当たり前)
一番下にはみ出さず、セクション間に隙間を作らない方法は何かありませんでしょうか?
尚、補足ですが詳細セクションとグループヘッダーセクションやグループフッターセクションページフッターセクションとの間には太線が引かれているため隙間があるのかもしれませんが隠れてしまい見た目上隙間は無いようになっています。
段々とずれてきてしまいすみません。
あと少しだと思うのですが、もう少しよろしくお願いします。
エラーが出ていたためまだ実行結果を見ていませんでした。
もう一度コピペし直したところエラーは出なくなりました。
あと、読解が間違っていたようです。(2024.1.9)でもpos1=8、pos2=17なのでl=8で条件式に入りますね。
この取得した日付をT_発注書取込の発注日フィールドに書き込む記述は、msgboxのところを書き換えればよいでしょうか?
そのエラーがでるのはどの行ですか。エラーのでる行を提示してください。
こちらで試してみましたが「発注書(2024.1.9).xlsx」でも問題なく 2024/01/09 という日付が返りますが。
実際に試してみましたか。
ありがとうございます。
命名規則に抵触しているのだろうと探していたのですが「こういう風につけましょう」しか見つけられず、「ダメな理由」を見つけることが出来ずにいたのでとても助かりました。
今あるものを確認して修正します。
こちらのコードを試したところ、Beref引数の型が一致しませんとエラーが出るのですが、どうすればよろしいでしょうか?
また、このコードの読解をしていたところ、8文字かそれ以上でなければ日付かどうか判定する条件式に入らないと思うのですが、ファイル名が発注書(2024.1.9).xlsxのように8桁ではない場合、どうすればよいでしょうか?
テキストボックス名が、
txt_1月, txt_2月 ・・・・txt_12月
だとして、
Controlsで文字列のテキストボックス名でアクセスできますので、
それを利用してループ処理します。
テキストボックスは非表示にして、Printメソッドで表示してますので、そちらの方を修正する必要があります。
本題から遠いので個別に
ニンゲンが記述するものはすべて「文字」なので、それが計算してほしいモノ(計算式)なのか、名前の指定なのかはそれだけでははっきりとしません
例えば「1 + 1」という名前のテキストボックスを作ったらそれを指定するときはどうしたらいいでしょうか?
ACCESSは開発を楽にするためにある程度自動認識でこれらの判別をしています
Me.1月
という記述はその自動認識によって構文エラーとなるような記述ということですねそれがオブジェクトの名前による指定であると明記する場合には
[]
で囲みます。Me.[1月]
とすれば正常に動作します命名規則(の一部)というやつですが、どんな文字でもいいからと言って本当にどんな名前にしてもいいというわけではないということですね
可能な限り数字や記号から始まる名前を付けるのはやめましょう
適当にサンプルで作ったのはこんな感じですね
オブジェクトの表示にはいろんな「隙間」があるので影響あるものを見つけて適切に調整する必要はあると思います
1.数字を桁区切り+¥がついた通貨型で表示したい
2.指定した場所から左揃えではなく右揃えで表示したい
3.同じような書式設定にしたいものが複数あるが、同じコードを繰り返す以外のやり方はないのか?
1に関しては
上記のコードだと下記の画像の様に桁区切りも¥もない数字になってしまい、以下を試しました。
.text → SetFocusがレポートの印刷プレビューではできない
.Value → 値を代入できないとエラーが出る
.Format = "Currency" → 何も変化なし
Me.請受金額月額 = Format(Me.請受金額月額, "\#,##0") → エラーで進まない
という感じで、結局希望する「協力会社1回金額」のような表示にはできませんでした。
2に関しては
上記コードだと左揃えだったので
としたらテキストボックスよりもだいぶ右の方に表示されました。
尚、よくわからずに
にしてみましたが、当然エラーでした。
3に関しては
まず、レコードによっては値がNullの場合があるため上記のコードにしています。
テキストを上下中央に配置したいテキストボックスは
テキストが1行のものが15(画像の請求回数・請受金額月額・協力会社1回金額・txt_1月~12月まで)、複数行の可能性があるものが2(協力会社名・作業内容)ありますが、複数行表示の可能性があるものは最悪このままでも、と思っていますが上記のようなコードをあと13書くのはコードがかなり冗長になるので避けたいと思いつつ、いい方法が見つけられませんでした。
(余談ですが、当初テキストボックスの名前が「1月」だったのですが、『Me.1月』にするとエラーになってしまい上記の様に『txt_1月』に変更しました。エラーの理由(規則?)を探しましたが見つけられませんでした)
1~3に関し、どうにかクリアしたいのですがもう少し教えていただけると助かります。(当初の質問とずれて来てすみません、問題があるようでしたら新たなスレッドを立てます)
よろしくお願いします。
色々試したのですがhirotonさまのコード、短くてできればそれにしたかったのですが、真ん中にはなってくれず…
hatenaさまの以下の上下中央(レス番号12)コードを元に上下中央にしたいテキストボックス全てに書く方式になりそうです。
【参考コード】
【現状のコード】
ただ、以下のことが出来ずに半日悩んでいました。
hatenaさま
早速なるアドバイスをいただき、ありがとうございました(深々お辞儀)。
自分が想定していた内容、そのものズバリを解りやすく書いていただき、腑に落ちました。
当人が何故「テーブルのコピー」→「リネーム」を洗い替えできていると認識しているのかは
相変わらずナゾですが(しかも自称SE・・・)、
とりあえず「データベースの最適化/修復」を定期的に行うように何とか説得をして、
業務手順資料も修正してもらうように働きかけをしておきます。
それにしても、自称って困りものですね。。。(何を言っても耳を貸さないので)
まず、データベースのデータの管理方法は、エクセルのブックなどのファイルの管理方法とは異なります。
ブックならディスクからメモリ上に読み込んで、更新後ディスクに上書きします。
つまりディスク上のデータ位置は連続しているし、データの順番も固定されています。
Accessの場合は、テーブルデータの更新、削除、追加した場合、データの連続性、データの並び順は保証されません。
更新した場合同じ位置に上書きされるとは限りません。
削除した場合、実際に削除されるわけではなく削除フラグを立てるだけです。
追加した場合、ファイルの最後に追加されるわけでもありません。
これは大量のデータを扱うデータベースに最適化された設計です。
つまり更新、削除、追加を繰り返すと、データの連続性はなくなり、データの並び順もごちゃごちゃになります。
このままではファイルサイズは肥大して、パフォーマンスも落ちます。
データ破損の危険性も高まります。
この非連続性を解消して、並び順もキーフィールドに合致するようにするのが「データベースの最適化/修復」という処理です。
Accessデータベースにおいて定期的な「データベースの最適化/修復」というのは必須といえます。
「テーブルのコピー」→「リネーム」で解決できる場合もあるかもしれませんが、それでは上記の非連続性は解消されませんので根本的な解決にはならないでしょう。
また、データペースにおいて、リレーションシップが設定されていれば、コピー→リネームの前にリレーションシップの削除、リネーム後にリレーションシップの再設定という作業も必要になり煩雑になります。設定ミスで破損なんてことにもなりかねません。
「データベースの最適化/修復」でやっていることは、元のデータベースファイルからデータをキーフィールドの並び順に読み込んで、新規データベースファイルに書き込むという処理をして、完了後に元のファイルを削除して新規ファイルをリネームするということをしています。つまり「洗い替え」をしているということだと思います。
経験上「データベースの最適化/修復」を定期的にやっていればめったに破損することはないです。
ただ、絶対破損しないということはないし、「データベースの最適化/修復」で修復できない場合もないとは言えないので、定期的にデータベースファイルのバックアップを取るという運用も必須でしょう。
おお!!素晴らしいアイデアですね。
印刷時でも余白は変更できるとは思いもよりませんでした。
表形式のレイアウトで高さを揃えるというのも思いつきませんでした。
これには関しては、
Me.Height
でカレントセクションの印刷時拡張時の高さを取得できます。お二方とも、お返事ありがとうございます。
btn決定 → cbo選択肢_AfterUpdate → cbo選択肢_BeforeUpdate → Form_Close → Form_Load
みたいなのを見ると もやもや するわけですけど、
VBEの「モジュール全体を連続表示」では、
プロシージャが長い、多い状態になるとスクロールしてる場合じゃないですよね。
Word のナビゲーションウィンドウのようなものも無く。
私はひとり情シスですが、詳しいお二方のご意見を伺えてよかったです。
ありがとうございました。
いろいろ試してみました
Format
イベント/Print
イベントで出来ること/できないことできないことむずかしいですねぇ「Ctl1月」テキストボックスは「自社用」テキストボックスと同時に選択してレイアウト→表形式にしておきます
h
は固定値なので直接記述してもいいかなとも思います例)
Print
イベントでは多くのプロパティが変更できませんそんな中でも余白のプロパティは変更できるようです
高さのプロパティは変更できないので、印刷時拡張が設定されたテキストボックスと表形式のレイアウトを組んでおくことで高さが揃うようにします
印刷時拡張後の高さは印刷時拡張プロパティを「はい」にしたコントロールから取得できます(詳細セクションの高さでは取得できませんでした)
読み込み時のはエラーが出る原因の話だけですね、>> 11でhatenaさんにも補足していただいていますが
だけで済むので簡単です。(デフォルトでは存在しないレポートヘッダーの組み込みも不要です)
やりとりを軽く眺めていましたが、そもそも「フォーマット時に
Me.詳細.Height
がうまく取得できない問題」が問題なのに、hatenaさんのコードもフォーマット時でMe.詳細.Height
を使っているのでうまくいかないんじゃないかなーって思ってたのでその通りになったなーって印象です下記はテキストボックス1のテキストを上下中央に表示します。
Report_Loadならレポートヘッダがなくても動作するのでそれがいいですね。
上下中央に配置するテキストが画像のように金額だったり、「〇」だけなら、
印刷時イベントでPrintメソッドで出力する方法がいいですね。
これなら配列に高さを格納するコードは不要です。
Report.Print メソッド (Access) | Microsoft Learn
印刷時拡張で2行以上になる場合とかは使えないですし、ユニコード非対応なのでS-Shiftにない文字があると文字化けするのでその場合は、使えませんが。
私もhirotonさんと同じですね。
「必要なモノを適切な名前で、適切なモジュール内に記述」
この一言で言いつくされていると思います。
大きなプロジェクトだとプロシージャだけで百をこえることは普通ですし、追加、修正のたびにどのような順が適切かなんて考えてないです。
いかに適切な名前をつけるかに集中ですね。