OpenArgsはレポートFormat時イベントに下記でしてます(念の為にレポートの非表示テキストボックス[tx_Args]のコントロールに設定してます)
” 'フォームからのOpenArgs[tx_Args]を分割して代入
Dim v As Variant
v = Split(Nz(Me.[tx_Args]), ",")
Me.tx_kubun = v(0)
Me.tx_sort = v(1) ”
SELECT
M_棟.物件ID, M_棟.棟名, Q_F.[フロア数], Q_R.部屋数
FROM
(M_棟 INNER JOIN
(
SELECT M_棟.物件ID, M_棟.棟ID, M_棟.棟名, Count(M_フロア.[フロアID]) AS フロア数
FROM M_棟
INNER JOIN M_フロア
ON M_棟.物件ID = M_フロア.物件ID AND M_棟.棟ID = M_フロア.棟ID
GROUP BY M_棟.物件ID, M_棟.棟ID, M_棟.棟名
) AS Q_F
ON M_棟.物件ID = Q_F.物件ID AND M_棟.棟ID = Q_F.棟ID
)
LEFT JOIN
(
SELECT M_部屋.物件ID, M_フロア.棟ID, M_棟.棟名, M_部屋.[フロアID], Count(M_部屋.部屋ID) AS 部屋数
FROM
(M_棟 INNER JOIN M_フロア ON M_棟.物件ID = M_フロア.物件ID AND M_棟.棟ID = M_フロア.棟ID)
INNER JOIN M_部屋
ON M_フロア.物件ID = M_部屋.物件ID AND M_フロア.棟ID = M_部屋.棟ID AND M_フロア.[フロアID] = M_部屋.[フロアID]
WHERE M_部屋.[フロアID]='00001'
GROUP BY M_部屋.物件ID, M_フロア.棟ID, M_棟.棟名, M_部屋.[フロアID]
) AS Q_R
ON M_棟.物件ID = Q_R.物件ID AND M_棟.棟ID = Q_R.棟ID
WHERE M_棟.物件ID='00165'
Function 締め日付(締め実日, 売上日付)
締め日付 = IIf(IsNull(締め実日), 売上日付, DateSerial(Year(売上日付), Month(売上日付) + IIf(Day(売上日付) > 締め実日, 1, 0), 締め実日))
End Function
あと、VBAを使うならIf構文を使った方が読みやすいように思います。
Function 締め日付(締め実日, 売上日付)
If IsNull(締め実日) Then
締め日付 = 売上日付
Else
締め日付 = DateSerial(Year(売上日付), Month(売上日付), 締め実日)
If Day(売上日付) > 締め実日 Then 締め日付 = DateAdd("m", 1, 締め日付)
End If
End Function
SELECT
M_棟.物件ID, M_棟.棟名, Q_F.[フロア数], Q_R.部屋数
FROM
(M_棟 INNER JOIN Q_F
ON M_棟.棟ID = Q_F.棟ID AND M_棟.物件ID = Q_F.物件ID)
INNER JOIN Q_R
ON M_棟.棟ID = Q_R.棟ID AND M_棟.物件ID = Q_R.物件ID
WHERE M_棟.物件ID="00165";
つぎにサブクエリにしたいクエリ名(Q_F, Q_R)の前に下記のように () AS を挿入します。
SELECT
M_棟.物件ID, M_棟.棟名, Q_F.[フロア数], Q_R.部屋数
FROM
(M_棟 INNER JOIN () AS Q_F
ON M_棟.棟ID = Q_F.棟ID AND M_棟.物件ID = Q_F.物件ID)
INNER JOIN () AS Q_R
ON M_棟.棟ID = Q_R.棟ID AND M_棟.物件ID = Q_R.物件ID
WHERE M_棟.物件ID="00165";
この挿入したカッコの中に、それぞれのクエリのSQLを挿入します。
もちろん挿入する前にそれぞれのSQLも読みやすいようにインデントを入れておきます。
すると下記のような感じになります。
SELECT
M_棟.物件ID, M_棟.棟名, Q_F.[フロア数], Q_R.部屋数
FROM
(M_棟 INNER JOIN
(
SELECT
M_棟.物件ID, M_棟.棟ID, M_棟.棟名, Count(M_フロア.[フロアID]) AS フロア数
FROM
M_棟 INNER JOIN M_フロア
ON M_棟.棟ID = M_フロア.棟ID AND M_棟.物件ID = M_フロア.物件ID
GROUP BY M_棟.物件ID, M_棟.棟ID, M_棟.棟名
) AS Q_F
ON M_棟.棟ID = Q_F.棟ID AND M_棟.物件ID = Q_F.物件ID
)
INNER JOIN
(
SELECT
M_部屋.物件ID, M_フロア.棟ID, M_棟.棟名, M_部屋.[フロアID], Count(M_部屋.部屋ID) AS 部屋数
FROM
(M_棟 INNER JOIN M_フロア
ON M_棟.物件ID = M_フロア.物件ID AND M_棟.棟ID = M_フロア.棟ID)
INNER JOIN M_部屋
ON M_フロア.物件ID = M_部屋.物件ID AND M_フロア.棟ID = M_部屋.棟ID AND M_フロア.[フロアID] = M_部屋.[フロアID]
GROUP BY M_部屋.物件ID, M_フロア.棟ID, M_棟.棟名, M_部屋.[フロアID]
) AS Q_R
ON M_棟.棟ID = Q_R.棟ID AND M_棟.物件ID = Q_R.物件ID
WHERE M_棟.物件ID)="00165";
Function PreviewReport(rptName As String)
Dim cuDt1 As Variant, cuDt2 As Variant, urDt1 As Variant, urDt2 As Variant
Dim stArgs1 As Variant, stArgs2 As Variant
cuDt1 = Me.[cb売上年月Fr] & "/01"
cuDt2 = CDate(Me.[cb売上年月To] & "/01")
cuDt2 = DateSerial(Year(cuDt2), Month(cuDt2) + 1, 0)
urDt1 = Me.[cb売上日付Fr]
urDt2 = Me.[cb売上日付To]
stArgs1 = "※指定期間: " & cuDt1 & "~" & cuDt2
stArgs2 = "★指定期間: " & urDt1 & "~" & urDt2
If IsNull(urDt2) Then
DoCmd.OpenReport rptName, acViewPreview, OpenArgs:=stArgs1
ElseIf Not IsNull(urDt2) Then
DoCmd.OpenReport rptName, acViewPreview, OpenArgs:=stArgs2
End If
End Function
Sub PreviewReport(rptName As String)
Dim cuDt1 As Variant, cuDt2 As Variant, urDt1 As Variant, urDt2 As Variant
Dim stArgs1 As Variant, stArgs2 As Variant
cuDt1 = Me.[cb売上年月Fr] & "/01"
cuDt2 = CDate(Me.[cb売上年月To] & "/01")
cuDt2 = DateSerial(Year(cuDt2), Month(cuDt2) + 1, 0)
urDt1 = Me.[cb売上日付Fr]
urDt2 = Me.[cb売上日付To]
stArgs1 = "※指定期間: " & cuDt1 & "~" & cuDt2
stArgs2 = "★指定期間: " & urDt1 & "~" & urDt2
If IsNull(urDt2) Then
DoCmd.OpenReport rptName, acViewPreview, OpenArgs:=stArgs1
ElseIf Not IsNull(urDt2) Then
DoCmd.OpenReport rptName, acViewPreview, OpenArgs:=stArgs2
End If
End Sub
Private Sub コマンド1_Click()
Call PreviewReport("●●●")
End Sub
Function RemoveDuplicatesX(ByVal argA As Variant _
, ByVal argB As Variant _
, Optional ByVal argMinimum As Long = 3) As Variant
RemoveDuplicatesX = argB
Dim lA As Long, lB As Long, l As Long
lA = Len(Nz(argA))
lB = Len(Nz(argB))
If lA < argMinimum Or lB < argMinimum Then Exit Function
If lB < lA Then l = lB Else l = lA
Dim i As Long, j As Long
For i = l To argMinimum Step -1
For j = 1 To lA - i
RemoveDuplicatesX = Replace(RemoveDuplicatesX, Mid(argA, j, i), "")
Next
Next
End Function
Private Sub コマンドボタン名_Click()
'// 重複と見なす文字列の最小連続長は関数の第三引数で指定します(省略時は3)
Me.テキストボックスB.Value = _
RemoveDuplicatesX(Me.テキストボックスA.Value, Me.テキストボックスB.Value)
End Sub
Function OnesideUniqueX(ByVal argA As Variant _
, ByVal argB As Variant _
, Optional ByVal argMinimum As Long = 3 _
, Optional ByVal argPos As Long = 1) As Variant
OnesideUniqueX = argB
Dim i As Long
Dim j As Long
Dim buff As String
If (LenB(Nz(argA)) = 0 Or LenB(Nz(argB)) = 0) Then Exit Function
If (argMinimum < 1 Or argPos < 1) Then Exit Function
For i = argPos To Len(argB) - argMinimum + 1
If (InStr(1, argA, Mid$(argB, i, argMinimum), vbBinaryCompare) > 0) Then
buff = Mid$(argB, i, argMinimum)
For j = i + argMinimum To Len(argB)
buff = buff & Mid$(argB, j, 1)
If (InStr(1, argA, buff, vbBinaryCompare) = 0) Then
OnesideUniqueX = _
OnesideUniqueX(argA, Left$(argB, i - 1) & Mid$(argB, j), argMinimum, i)
Exit Function
End If
Next j
OnesideUniqueX = Left$(argB, Len(argB) - Len(buff))
Exit Function
End If
Next i
End Function
Private Sub コマンドボタン名_Click()
'// 重複と見なす文字列の最小連続長は関数の第三引数で指定します
Me.テキストボックスB.Value = _
OnesideUniqueX(Me.テキストボックスA.Value, Me.テキストボックスB.Value, 3)
End Sub
Function RemoveDuplicates(ByVal argA As Variant, ByVal argB As Variant) As Variant
RemoveDuplicates = argB
If argA <> "" And argB <> "" Then
Dim i As Long
For i = 1 To Len(argA)
RemoveDuplicates = Replace(RemoveDuplicates, Mid(argA, i, 1), "")
Next i
End If
End Function
Function OnesideUnique(ByVal argA As Variant, ByVal argB As Variant) As Variant
OnesideUnique = argB
If (LenB(Nz(argA)) = 0 Or LenB(Nz(argB)) = 0) Then Exit Function
Dim i As Long
Dim c As Long
Dim buff() As String
For i = 1 To Len(argB)
If (InStr(1, argA, Mid$(argB, i, 1), vbBinaryCompare) = 0) Then
ReDim Preserve buff(c)
buff(c) = Mid$(argB, i, 1)
c = c + 1
End If
Next i
If (UBound(buff) > -1) Then
OnesideUnique = Join(buff, "")
End If
End Function
hatenaさん コードは下記です
” Dim rptName As String, opg1 As Integer, opg2 As Integer
Dim txKubun As String, txSort As String, stArgs As String
rptName = "R年度別売上集計_Cross_顧客と営業担当別"
opg1 = Me.[opg_kubun].Value
opg2 = Me.[opg_Sort].Value
Select Case opg1 '担当区分
Case 1
txKubun = "社内営業担当:設定なし"
Case 2
txKubun = "社内営業担当:A"
Case 3
txKubun = "社内営業担当:B"
End Select
Select Case opg2 '並べ替え設定
Case 1
txSort = "※顧客社名で並べ替え"
Case 2
txSort = "●顧客合計金額を昇順で設定"
Case 3
txSort = "■顧客合計金額を降順で設定"
End Select
'レポートに渡すOpenArgsを組立
stArgs = txKubun & "," & txSort
MsgBox stArgs
DoCmd.OpenReport rptName, acViewPreview, WhereCondition:=Me.Filter, OpenArgs:=stArgs
DoCmd.Maximize ”
OpenArgsはレポートFormat時イベントに下記でしてます(念の為にレポートの非表示テキストボックス[tx_Args]のコントロールに設定してます)
” 'フォームからのOpenArgs[tx_Args]を分割して代入
Dim v As Variant
v = Split(Nz(Me.[tx_Args]), ",")
Me.tx_kubun = v(0)
Me.tx_sort = v(1) ”
フォームのレポート開くコマンドボタンの全コードを提示してください。
stArgsをどのように設定しているか知りたいので。
ありがとうございます。
「書式設定とレイアウトを保持したままデータをエクスポートする」もいれてるんですが、00.00のままです…
意味あるか分かりませんが、テーブルの書式変更してる最中です…
hatenaさん ありがとうございます。
フォームのオプションボタンopg2を下記でしてます
Select Case opg2 '並び替え設定
Case 1
Me.OrderBy = "[ふりがな] ASC"
Case 2
Me.OrderBy = "[顧客合計] ASC"
Case 3
Me.OrderBy = "[顧客合計] DESC"
End Select
Me.OrderByOn = True
レポートのレコードソースはフォームと同じクロス集計クエリを使ってます。
エクスポートするときに
「書式設定とレイアウトを保持したままデータをエクスポートする」のオプションにチェックを入れて実行したらどうでしょう。
現状、フォームの並べ替えはどのようにしていますか。
OrderByプロパティを利用しているのなら、それをOpenArgs引数でレポートに渡してレポート側でOrderByプロパティに設定すればいいでしょう。ただ、現状のコードをみるとOpenArgs引数はすでに利用しているようなので工夫が必要です。
レコードソースのクエリで並べ替えをしているなら、その並べ替えの設定をレポートのレコードソースにも反映させることになります。
どちらにしても、現状、フォームの並べ替えをどのようにしているかの詳細な情報が必要です。
そのクエリをどのようなレイアウトでレポートに出力したいのでしょうか。
サブレポートを使わなくても、レポートは機能豊富ですのでたいていのものは作成できます。
私自身はサブレポートを使うことはほとんどありません。
例えば、下記のようなレイアウトで出力したいのなら、
品目ID と 名称 の「重複データ非表示」プロパティを「はい」にするだけです。
ほかにもグループ化の機能をつかってグループヘッダー、グループフッターをうまく使えばたいていの帳票レイアウトは可能です。
皆様、ご回答ありがとうございます。
おかげさまでできました。
hatena様、副クエリの作り方を教えていただきありがとうございます。
sk様、"00001"が決め打ちなのは、M_部屋がの構成が以下の通りだからです。
【M_部屋】
物件ID
棟ID
フロアID
部屋ID
・
・
部屋IDは、棟IDごと、フロアIDごとに、"00001"、"00002"…とあり、
棟ごとフロアごとの部屋数ではなく、棟ごとの部屋数だけを表示したいためです。
朱様
hatena様の例をもとに、1から作り直してみたので、
エラーの原因は後ほど確認してみます。
ユーザレビューを行った結果、少し仕様が変わり、M_部屋にデータがなくても、
棟名と棟ごとのフロア数は表示してほしいとの事でした。
出来上がったものを掲載しておきます。
SELECT
M_棟.物件ID, M_棟.棟名, Q_F.[フロア数], Q_R.部屋数
FROM
(M_棟 INNER JOIN
(
SELECT M_棟.物件ID, M_棟.棟ID, M_棟.棟名, Count(M_フロア.[フロアID]) AS フロア数
FROM M_棟
INNER JOIN M_フロア
ON M_棟.物件ID = M_フロア.物件ID AND M_棟.棟ID = M_フロア.棟ID
GROUP BY M_棟.物件ID, M_棟.棟ID, M_棟.棟名
) AS Q_F
ON M_棟.物件ID = Q_F.物件ID AND M_棟.棟ID = Q_F.棟ID
)
LEFT JOIN
(
SELECT M_部屋.物件ID, M_フロア.棟ID, M_棟.棟名, M_部屋.[フロアID], Count(M_部屋.部屋ID) AS 部屋数
FROM
(M_棟 INNER JOIN M_フロア ON M_棟.物件ID = M_フロア.物件ID AND M_棟.棟ID = M_フロア.棟ID)
INNER JOIN M_部屋
ON M_フロア.物件ID = M_部屋.物件ID AND M_フロア.棟ID = M_部屋.棟ID AND M_フロア.[フロアID] = M_部屋.[フロアID]
WHERE M_部屋.[フロアID]='00001'
GROUP BY M_部屋.物件ID, M_フロア.棟ID, M_棟.棟名, M_部屋.[フロアID]
) AS Q_R
ON M_棟.物件ID = Q_R.物件ID AND M_棟.棟ID = Q_R.棟ID
WHERE M_棟.物件ID='00165'
Accsessでは一番外側のWHERE以下以外で項目以外を条件に指定するとなぜかエラーになったような。
【エラーの出るSQL文】で途中に入ってる((M_棟.物件ID)="00165")がエラーの原因でしょうか。
提示されている【Q_F】【Q_R】にはないのに、なぜいきなり出てきた?という気はしますが。
数量と単価の関係性を逆にかいてしまいました。数量が多い方が安い見積りです。
質問内容とは関係ないかもしれませんが。。。
その後、期日の方も下記で出来ました(少し苦労しましたが)
”Function 支払期日(支払月間 As Variant, 支払日間 As Variant, 締め日付 As Date, 支払実日 As Variant) As Date
If IsNull([支払月間]) Then
支払期日 = DateAdd("d", [支払日間], [締め日付])
Else
支払期日 = DateSerial(Year([締め日付]), Month([締め日付]) + [支払月間], [支払実日])
If [支払実日] = 0 Then 支払期日 = DateSerial(Year([締め日付]), Month([締め日付]) + [支払月間] + 1, [支払実日])
End If
End Function”
hirotonさん色々と貴重なアドバイスありがとうございました。hatenaさんも毎回ありがとうございます。
hatenaさん ありがとうございました。勉強になります。
関数結果を細かく見ると10/31(正)が10/30(誤)になったりしてましたが、下記で正確にいけました。
”If Day(売上日付) > 締め実日 Then 締め日付 = DateSerial(Year(売上日付), Month(売上日付) +1,締め実日)”
ちょっと焦りましたが、これでいけました。
大変お世話になりました。
If文は複数行で書く構文と、1行で書く構文があります。
1行構文
複数行構文
条件が成立するときに実行するときのステートメントが一つのときは1行で書くことができます。(複数行でかいてもいいですが。)
つまり、
は、下記と同等です。
hirotonさんから適切なアドバイスがありますが、変数の型は省略しない方がいいというのは私も同意見です。
Accessの場合は、フィールドの値を引数とすることが多くなるので、フィールドのデータ型やプロパティ設定と合わせるのがいいでしょう。
Null値になる可能性がある(値要求=いいえの場合)ならVariant型、
Null値になる可能性がない(値要求=はいの場合)ならフィールドのデータ型と同じにする。
戻り値の型もNull値を返す必要性がある場合はVariant型、Null値を返す必要性がない場合は想定する型で宣言します。
色々詳細をありがとうございました。支払実日の0は末日になります。関数に出来ました。
”Else
締め日付 = DateSerial(Year(売上日付), Month(売上日付), 締め実日)
If Day(売上日付) > 締め実日 Then 締め日付 = DateAdd("m", 1, 締め日付) ” の様な記述ができるのですね。初めて知りました。この場合Ifが2つあってもEnd Ifは1つなのですね。
質問文を頑張って読み取って「支払実日の0は末日指定なのだろう」と思ってますが合ってますよね?
※VBAで解釈できない計算式(SQL記述)の場合はこの方法ではうまくいかない場合があります
ろくに計算式を見ないで回答してしまっていてアレなんですが、今回の内容だけでも
NULLの判定はVBA用の記述にする必要がありますね※VBA記述のマナーは無視しているので~
VBA記述には省略可能なものがありますが、記述しておくのが一般的なものや、問題なくとも意味合いが正確でないものもあります
Function ステートメント
ざっくりいうと、データ型はしっかり記述したほうが良いです
締め実日はNULLを扱うため、
Variant型である必要があります。また、データ型の省略時はVariant型となるため、省略しても同じですが、明示することにより、NULLを扱うことがあるし、それを意図してやっているということが読み取れるようになります逆に、そのほかの引数についてはしっかりそれぞれのデータ型を使うと指定(制限)をしておきましょう
関数の戻り値のデータ型
Function 締め日付(締め実日 As Variant, 売上日付 As Date) As Date
を記述するかどうかは個人差が出そうですが、日付型なら日付型を指定しておくと諸所で日付型のデータとして扱ってくれるのでよりよいと思われます(文字配置の「標準」が右寄せになったりとか)
あと、変数の名前からデータの内容がいまいち正確でないものには何か手を入れたほうがいいです
「日付」に「0日」はありませんし、「0の指定が1の1つ前ではない」ので、直感と実態が合わなくなります。末日指定をどうデータベース化するか?は悩みどころではありますが、とりあえず今回はコメント記述で対応ということで
あとはまぁ、「1行で記述する必要はない」ので、入れ子になりすぎて見づらい記述を分解するとかですかね。どこまでやるかはその時の内容次第です
VBAは、Is Null は使えないので、代わりにIsNull関数を使います。
あと、VBAを使うならIf構文を使った方が読みやすいように思います。
hirotonさん ありがとうございます。
”※VBAで解釈できない計算式(SQL記述)の場合はこの方法ではうまくいかない場合があります
※VBA記述のマナーは無視しているので、ユーザー定義関数がうまく動作することが確認出来たらVBA記述として望ましい記述か?を別途見直してみるとよいです”とありますが、マナー無視している事になるのでしょうか?(すみません知識不足で)
[M_部屋]の[フロアID]に対する条件値は固定なのでしょうか。
それとも、その部分も変数で指定しているのでしょうか。
もし前者である場合、"00001"を指定しているのはどのような理由からなのでしょうか。
コード(SQL構文、計算式等)をそのまま記述するとこの掲示板用のMarkdown記述と解釈されて意図しない整形がされてしまうことがあるので、コードブロックを使って記述しましょう
もっとも単純には、計算式で指定しているフィールドを重複を省いて引数において、そのまま戻り値に計算式を指定し、フィールド部分を引数に置き換えればユーザー定義関数化ができます
※VBAで解釈できない計算式(SQL記述)の場合はこの方法ではうまくいかない場合があります
※VBA記述のマナーは無視しているので、ユーザー定義関数がうまく動作することが確認出来たらVBA記述として望ましい記述か?を別途見直してみるとよいです
クエリで使うときはそれぞれ
または、締め日付を求めずに支払期日を求める場合は、支払期日の締め日付指定部分に締め日付を求める関数を指定すればよいでしょう
質問の結構複雑なSQLを読み解くのは骨なので、
私が複数クエリをサブクエリを使って一つにまとめる場合の手法を紹介しておきます。
まず、クエリデザインビューから作成したSQLは不必要な()が多くなり読みづらいので、不要なカッコは除去します。
その後、階層関係が分かりやすいように適切なインデントを付けて読みやすくします。
インデントの付け方は人それぞれの好みがあるので工夫して自分が読みやすいようにしてください。
例えば質問の最初のSQLなら、自分なら下記のようにします。
つぎにサブクエリにしたいクエリ名(Q_F, Q_R)の前に下記のように () AS を挿入します。
この挿入したカッコの中に、それぞれのクエリのSQLを挿入します。
もちろん挿入する前にそれぞれのSQLも読みやすいようにインデントを入れておきます。
すると下記のような感じになります。
提示のSQLを機械的につなげただけのものなので、希望の結果になるかどうかはそちらでしっかり確認してください。
回答ありがとうございました。
前からの仕様だったのですね。失礼いたしました。
バージョン管理も参考とさせていただきます。
ありがとうございました。
hatenaさん ありがとうございます。すごいアイデアですね。参考にしてみます。
お世話になりました。
エクスポート先の本番用ファイル内のフォームがそうなるということですか。
当方の環境は365ですが、確認してみたらそうなりますね。
私のブログの下記の記事によると、「エクスポートすると作成日、更新日ともエクスポートした日時になります」とのことですので、当時(2015年)からそのような仕様だったようですがが。
上記の記事では、説明プロパティにバージョン情報を入力しておいて、それを利用してはどうかと提案してます。
ちなみに、私も開発用と本番用は分けてますが、開発用で更新した場合は個別にエクスポートせずにファイルごと上書きしてますので、そのようなことで困ったことはないです。
ファイルのバージョン管理は、バージョン管理用のテーブルを作成して、そこにバージョンNo、更新日を格納して利用してます。
オブジェクトを個別にエクスポートすると、ファイル破損の危険性が高いような気がしますので、開発用のファイルを更新したら、開発用府。イルを最適化してから本番用ファイルに上書きするという方法をとってます。古い記事ですが下記もご参考に。
複数ユーザーで共有している場合のフロントエンドファイルのバージョンアップ - hatena chips
「発行済みというフィールド」がないのに、どのようにフォーム上に展開するのでしょうか。
それとも、そのフラグを保存する必要はなくその場限りのものでいいのなら、下記のページの方法が利用できます。
hatena様
1発解決でした!
そこそこ時間かけて四苦八苦しましたが、教えていただいた記述で1発でした。😮
ありがとうございました。
下記に修正してください。
質問のコードだとコントロールソースには下記の式が設定されます。
この場合「件」というフィールドかコントロールを参照しに行きますが、フォーム上にないのでName?エラーになります。
「件」は文字列でないとだめなので、引用符で囲む必要があります。
この件ですが解決しました。文字列型になっているのではと思いSQL最初のSELECT [売上年度], "" AS 年度合計の""を0にしたら通貨型になり、レポートでも設定できました。落ち着いて考えると分かる事でした。お騒がせしました。
hatenaさん ありがとうございます。
「開く時」「読み込み時」はCancel以外で出来る事が違うとは知りませんでした。大変勉強になります。
今回もお世話になり大変有り難うございました。
レポートの「開く時」イベントでは、デザインビューで設定できるプロパティのみ代入できます。
Valueプロパティには代入できません。
対策としては、ControlSourceプロパティに式として代入する。
=や引用符を付加する必要があります。
「読み込み時」イベントならValueプロパティに代入できます。こちらのほうがシンプルですね。
VBAを使わなくても、デザインビューでテキストボックスのコントロールソースでOpenArgsを参照することもできます。
Report.OpenArgs プロパティ (Access) | Microsoft Learn
hatenaさん ありがとうございます。これで1つにまとめる事が出来ました。
引数の事も大体理解できました。関数の()内と同じなのですね。Functionも使いこなす事が出来たら便利ですね。別で関数にしたい事があり、これはまたいずれ投稿したいと思ってます。
この関連で別内容なのですがレポート開くイベントにOpenArgsをレポートの非連結のテキストボックスに代入しようとすると代入出来ないエラーとなります。ラベルには代入できます(表示だけなのでそれでもOKですが)。それは何故なのでしょうか?
ラベル代入は下記コードです(これならエラーでません)。
Dim kikan As String
kikan = Nz(Me.OpenArgs, "")
Me.[label_kikan].Caption = kikan
引数の使い方が理解できたなら、
イベントプロシージャでCallで呼び出すのではなく、
フォームのデザインビューでイベントプロシージャに関数を設定して呼び出す方法も習得しておくといいでしょう。
SubをFunctionに変更しただけです。
フォームのデザインビューで「クリック時」プロパティに下記のように設定します。
ボタン毎にイベントプロシージャを記述する必要がなく、Functionを作成しておけばフォームのデザインビューの設定で済みます。
私のはこの方法を多用してます。
各ボタンのコードがレポートのみの異なるだけであとは同じなので、一つのプロシージャにまとめたいということでしょうか。
レポート名は引数で渡せばいいでしょう。「引数ってなに?」というレベルなら下記あたりを参照してください。
第29話「引数と戻り値ってなに?」1/4:引数とは…?|VBAとの出会い編|VBAエキスパートコラム
フォームモジュール
ご自身のコードと見比べればどこが変更されてるか一目だとおもいます。
Web検索をしてみると、少し古い情報で、同様の不具合が起きていることがあるようですね。しかも結局解決には至っていないようでした。コピーアンドペーストはwindowsのクリップボード、officeのクリップボード、と、外部機能と連携して機能しているので、謎の不具合に見舞われた場合、個人で自身の環境を調査するしかないのかもしれません
VBAを使うことになりますが、コピーアンドペーストを使わないようにすると問題が起きにくいと思います。
参考:レコードをVBAでまるごとコピー
mayuさん、バグのご指摘ありがとうございます。
理由も含めてのていねいな解説、納得です。
hatenaさんのコード、シンプルで素敵ですね
RemoveDuplicatesX 関数の内側ループ、終了の数値を 1 だけ足せば更に完璧かもです
mayuさんの上記の定義を仕様とする場合は下記のコードでもよさそう。
慧眼のhatenaさんが仰せのように、もし 連続した複数文字列を対象 とするのでしたら
「連続」の定義、つまり最小で何文字連続している必要があるのか
を明確にする必要があるでしょう
テキストボックスA = "あいうえおかきく"
テキストボックスB = "[@あいうえお@おかき@きくうえお@いうえおかういあいうえおかきおかく]"
Bの文字列で「 連続3文字以上で構成された語句でAに対する最長マッチ 」を繰り返す
と定義した場合、
[@あいうえお@おかき@きくうえお@いうえおかういあいうえおかきおかく]
Bからは、背景色を付与した5箇所の語句を検知( グレーアウト部分は長さが不足 )し、
最終的に
をご希望の結果とするサンプルも載せておきます
例をみると連続した複数文字列を対象にするようにも思えますが、
一文字単位でも重複していれば削除するという仕様であれば、
mayuさんのコードでいいでしょう。
単純に下記でも同様の結果になります。
シンプルに、テキストボックスBに入力された文字列を一文字ずつチェックしていけばいいでしょう
テキストボックスA, Bともにフォーム上に設置したコントロールだと仮定すると
コマンドボタンのクリック時イベント等で結果を確認するといいでしょう