みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。
1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)
You are not logged in.
今までLoop EndLoopで処理してましたが、レコード数が増えたため処理が重たくなりました。
調べるとLet関数でもLoop処理ができ速いと言うことですが使ったことがありません。
チャレンジも兼ねてお教えいただけなでしょうか?
Win FM11
処理内容は納品書で、すでに枠が印刷されている中に内訳を入れたいと思います。
レコード
顧客No. 商品名 ページにページNoを入れる
条件
納品書1枚は10行までなので1から10レコードはページに1、11から20までは2と言うように処理したいのです。
顧客が変わればまた、1から
1レコード Aさん えんぴつ 1
.
.
10レコード Aさん 消しごむ 1
11レコード Aさん ボールペン 2
.
.
20レコード Aさん サインペン 2
21レコード Aさん 分度器 3
22レコード Bさん えんぴつ 1
.
.
全レコードで終了
よろしくお願いします。
Offline
その明細は別テーブルに格納し、納品先毎に1レコードとした別テーブルのレコードから明細を呼び出すのが常套手段。
印刷時に10行毎に改頁するのならば、明細側でリスト表示をさせて、ヘッダ、フッタ で頭書きなどを作り、10行印刷するようにパートの高さを調整すれば良いです。
Offline
早速のご返答感謝します。
ええ、その方法は理解しています。
ですが、枠そのものをプレビューし印刷かPDF出力を選択しますのでイメージとして出したのです。
なのでLet関数でLoop処理を希望しています。
Offline
フィールド内容の全置換を計算式で
Let ( $RN = Case ( GetNthRecord ( 顧客No. ; Get ( レコード番号 ) - 1 ) = 顧客No. ; $RN + 1 ; 10 ) ; Div ( $RN ; 10 ) )
おお、こんな簡単なんですね、解決です。
感謝します。
これから、なぜこうなるのか解読し他のLoop文にも反映させたいと思います。
ありがとうございました。
Offline
その目的ならば、VirtualList を使えばもっと簡単ですよ。
普通にレイアウトしても、PDF化などもごく簡単な事です。画面上に配置できる物は、そのままPDF化できるのが FM の強みです。FM11 でしたら、PDFのフォーム上に差し込み印刷のような事も可能ですし。
Offline
調べるとLet関数でもLoop処理ができ速いと言うことですが使ったことがありません。
Let関数でLoop処理を希望しています。
上記のあたりが気になるので少し書いておきます。
フィールド内容の全置換を計算式で
Let ( $RN = Case ( GetNthRecord ( 顧客No. ; Get ( レコード番号 ) - 1 ) = 顧客No. ; $RN + 1 ; 10 ) ; Div ( $RN ; 10 ) )
この処理は、「Loop処理」の代わりに、「フィールド内容の全置換」を使う。と認識したほうが良いです。
「Loop処理」の代わりに「Let関数」を使ったのではありません。
例えば、
「フィールド:index」を作成し、
フィールド内容の全置換を計算式で
Case ( GetNthRecord ( 顧客No. ; Get ( レコード番号 ) - 1 ) = 顧客No. ;
GetNthRecord ( index ; Get ( レコード番号 ) - 1 ) + 1 ;
1 )
とすると、「フィールド:index」に顧客No.ごとの通し番号を振ることが出来ます。
フィールド:ページNo で、以下のように計算式を入れるとページNoが取得出来ます。
フィールド:ページNo|計算|DIV(index-1;10)
上記のように「Let関数」を使わない場合、もう一手間(1フィールド)必要になります。
「Loop処理」の代わりに、「フィールド内容の全置換」を使う。
一時的な計算の為の値の保持に「Let関数」を使う。
と認識しておいた方が混乱しません。
※
調べるとLet関数でもLoop処理ができ速い
コレは、「Let関数」を利用した「再起式」の事かもしれませんね。
Offline
Shinさんのご意見もありがとうございました。
ただ今回はLet関数をただただ、覚えたいと思い投稿した次第です。
qb_dpさん、詳しくとてもありがたいです。
確かに、再起式ですので正確にはLoop処理では無いですね。
ただ、結果が同じなら処理も速くスクリプト全体が見やすく、今後使えるところはこれに切り替えていきたいと思います。
できれば、極めたいとおもいます。
ありがとうございました。
Offline
相当古いですが、今も事情はほぼ変わってなさそうなので。
■ [設計] ループ的な処理の書き方 | FileMakerを考える
http://filemaker-kou.seesaa.net/article/148132326.html
Let()というよりEvaluate()による再帰評価を、ループと呼んでるのかも知れません。
Let関数を使った全置換で変数を使うと
結構変なことが起きるのでご注意を
例えば
Let($D=$D+1;$D)
という式を使って
数字フィールドに全置換を何度もかけて見てください。
同じレコードグループに繰り返していると
返ってくる数値が、だんだん増えて来ます。
つまり計算のたびに変数はクリアさないのです。
どこかで、変数をクリアしておく必要あります。
といっても これはFMO12までの問題で
それ以降解決されていれば問題はないとは思いますが。
Last edited by シャチ (2017-02-23 20:20:17)
Offline
共有ファイルだと他のユーザの処理とバッティングする可能性もありますね。
グローバルフィールドを使った非保存計算フィールド等にしたほうがいいかも。
LetとEvaluateによるループ計算処理で、その簡便さに対し、
ループ回数の低さ(大凡300回以下)が利便上の問題とされますが、
・入れ子の2重ループ式にするとカスタム関数の限界数(非末尾再帰1万回)
をも超えたループ回数も可能になります。(スピードは鈍足ですが)
・例えば、安全を見て1重の最大数を半分以下の125回に制限しても、
その2重ループは、 125X125=15,625 回となります。
Offline
Let関数だけの本があればいいのにな。
Let関数は奥が深すぎませんか?
qb_dpさん、一度ファイルメーカー本(中・上級者用)を書いてくれませんか?
qb_dpさんは、C++でプラグインも作られていますし。
あなたの情報はのちのち必須になると思います。
年齢がわからないので、もしかしたら若かったら凄い人ですよ。
年寄りなら若い人に知識を与えましょうよ。
Let関数を使った全置換で変数を使うと
結構変なことが起きるのでご注意
Let($D=$D+1;$D)
どこかで、変数をクリアしておく必要あります。
$変数を利用するソリューションでは、初期値の宣言を習慣付けています。
・クリアスタートなら、 $変数="" or $変数=0
・継続利用でも、あえて宣言 $変数=$変数
Let($D=$D+1; $D)
↓
Let([$D=Case(Get(レコード番号)=1;"";$D); $D=$D+1]; $D)
||
Let([$D=Case(Get(レコード番号)<>1;$D)+1]; $D)
Offline
初期化は必須ですよね。
スクリプト以外で使った場合の$変数のスコープは結構適当というか データビューアで定義しただけのでも次の計算まで残ってたりするし
バグじゃないならしっかり明記して欲しい。
Let()で束縛する場合、種類とスコープと衝突にご注意を。
これも古いですが、今も通じる話のはず。
■ FileMakerの変数 寿命やスコープのおさらい | FileMakerを考える
http://filemaker-kou.seesaa.net/article/189610098.html
■ $ローカル変数の衝突の検証 | FileMakerを考える
http://filemaker-kou.seesaa.net/article/189903546.html
前に
Let($D=$D+1;$D)
の式を書いたのですが、
よく変数名に$がなくてもいいと書かれています。
また、リファレンスにも書かれています。
が
Let(D=D+1;D)
で、良いかと思うのですが、
これは 式の確定の段階で
フィールド名が見つからないとアラートが出ます。(FMP12段階)
この辺りは、なぜなのかがわかりません。
Let関数や変数だけの詳細のリファレンスがいるかもしれませんね。
Offline
Dが定義されてないので参照できないですね。
$変数は、存在しない場合自動的に作られるけど、$なしのLet変数はLetの中でしか使えないのでLetで定義する必要がある。Let関数の外では参照できないので、全置換での連番の保存には使えません。
Dが定義されてないので参照できないですね。
$変数は、存在しない場合自動的に作られるけど、$なしのLet変数はLetの中でしか使えないのでLetで定義する必要がある。Let関数の外では参照できないので、全置換での連番の保存には使えません。
この辺りの仕様は、理解するには難しすぎるんではと思ったりもしますね。
改めてリファレンスを読んで見たんですが、難解でした。
Offline
例えば
Let ( [ D = 0 ; D = D + 1 ] ; D )
これはOKですよね。
Offline
例えば
Let ( [ D = 0 ; D = D + 1 ] ; D )
これはOKですよね。
しかし、これだと今回のような場合にはダメなんですよね
とにかく難しい仕様だと思います。
Offline
「フィールド内容の全置換」の場合は、
1レコード目
Let([$D=Case(Get(レコード番号)=1;"";$D); $D=$D+1]; $D)
$D=1
2レコード目
Let([$D=Case(Get(レコード番号)=1;"";$D); $D=$D+1]; $D)
$D=$D+1
$D=2
.....
となり、
ローカル変数で無い場合は、
1レコード目
Let([D=Case(Get(レコード番号)=1;"";D); D=D+1]; D)
D=1
2レコード目
Let([D=Case(Get(レコード番号)=1;"";D); D=D+1]; D)
前の「D」は引き継げないので
D=""
...
となる。
1レコード目 と 2レコード目 は、LET()の外なので「D」の値は、保持しない。
という認識で良いのでは。
Offline
Let([D=Case(Get(レコード番号)=1;"";D); D=D+1]; D)
でもだめで、引き継げないという以前に式がエラーになります。
Dを定義し終わる前にDの代入式(右辺)にDを書くと、変数名でなくフィールド名(テーブル名)と解釈されます。
あ~そうなんですね。
すみません。
Let([D=Case(Get(レコード番号)=1;"";D); D=D+1]; D)
は、未検証で書いてました。
Offline
[ Generated in 0.010 seconds, 8 queries executed - Memory usage: 575.69 KiB (Peak: 612.59 KiB) ]