初心者のFileMaker pro Q&A (旧掲示板)

みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。

1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)

You are not logged in.

Announcement

新しい掲示板は、こちら:https://fm-aid.com/forum/t/filemaker


#1 2017-02-22 15:58:02

やま爺
Member

Let関数でLoop処理を教えて下さい。

今まで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

#2 2017-02-22 16:21:10

Shin
Member

Re: Let関数でLoop処理を教えて下さい。

その明細は別テーブルに格納し、納品先毎に1レコードとした別テーブルのレコードから明細を呼び出すのが常套手段。
印刷時に10行毎に改頁するのならば、明細側でリスト表示をさせて、ヘッダ、フッタ で頭書きなどを作り、10行印刷するようにパートの高さを調整すれば良いです。

Offline

#3 2017-02-22 16:28:21

やま爺
Member

Re: Let関数でLoop処理を教えて下さい。

早速のご返答感謝します。
ええ、その方法は理解しています。
ですが、枠そのものをプレビューし印刷かPDF出力を選択しますのでイメージとして出したのです。
なのでLet関数でLoop処理を希望しています。

Offline

#4 2017-02-22 16:35:44

tim
Guest

Re: Let関数でLoop処理を教えて下さい。

フィールド内容の全置換を計算式で
Let ( $RN = Case ( GetNthRecord ( 顧客No. ; Get ( レコード番号 ) - 1 ) = 顧客No. ; $RN + 1 ; 10 ) ; Div ( $RN ; 10 ) )

#5 2017-02-22 16:52:05

やま爺
Member

Re: Let関数でLoop処理を教えて下さい。

おお、こんな簡単なんですね、解決です。
感謝します。
これから、なぜこうなるのか解読し他のLoop文にも反映させたいと思います。

ありがとうございました。

Offline

#6 2017-02-22 22:46:34

Shin
Member

Re: Let関数でLoop処理を教えて下さい。

その目的ならば、VirtualList を使えばもっと簡単ですよ。
普通にレイアウトしても、PDF化などもごく簡単な事です。画面上に配置できる物は、そのままPDF化できるのが FM の強みです。FM11 でしたら、PDFのフォーム上に差し込み印刷のような事も可能ですし。

Offline

#7 2017-02-23 12:00:08

qb_dp
Member

Re: Let関数でLoop処理を教えて下さい。

調べると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

#8 2017-02-23 12:38:21

やま爺
Member

Re: Let関数でLoop処理を教えて下さい。

Shinさんのご意見もありがとうございました。
ただ今回はLet関数をただただ、覚えたいと思い投稿した次第です。

qb_dpさん、詳しくとてもありがたいです。
確かに、再起式ですので正確にはLoop処理では無いですね。
ただ、結果が同じなら処理も速くスクリプト全体が見やすく、今後使えるところはこれに切り替えていきたいと思います。
できれば、極めたいとおもいます。
ありがとうございました。

Offline

#9 2017-02-23 15:17:39

honda
Guest

Re: Let関数でLoop処理を教えて下さい。

相当古いですが、今も事情はほぼ変わってなさそうなので。

■ [設計] ループ的な処理の書き方 | FileMakerを考える
http://filemaker-kou.seesaa.net/article/148132326.html

Let()というよりEvaluate()による再帰評価を、ループと呼んでるのかも知れません。

#10 2017-02-23 19:48:14

シャチ
Member

Re: Let関数でLoop処理を教えて下さい。

Let関数を使った全置換で変数を使うと
結構変なことが起きるのでご注意を

例えば
Let($D=$D+1;$D)
という式を使って
数字フィールドに全置換を何度もかけて見てください。
同じレコードグループに繰り返していると
返ってくる数値が、だんだん増えて来ます。
つまり計算のたびに変数はクリアさないのです。
どこかで、変数をクリアしておく必要あります。

といっても これはFMO12までの問題で
それ以降解決されていれば問題はないとは思いますが。

Last edited by シャチ (2017-02-23 20:20:17)

Offline

#11 2017-02-23 20:01:20

ぽんかん
Guest

Re: Let関数でLoop処理を教えて下さい。

共有ファイルだと他のユーザの処理とバッティングする可能性もありますね。
グローバルフィールドを使った非保存計算フィールド等にしたほうがいいかも。

#12 2017-02-23 22:27:53

Hiro
Member

Re: Let関数でLoop処理を教えて下さい。

LetとEvaluateによるループ計算処理で、その簡便さに対し、
ループ回数の低さ(大凡300回以下)が利便上の問題とされますが、
入れ子の2重ループ式にするとカスタム関数の限界数(非末尾再帰1万回)
   をも超えたループ回数も可能になります。(スピードは鈍足ですが)
・例えば、安全を見て1重の最大数を半分以下の125回に制限しても、
   その2重ループは、 125X125=15,625 回となります。

Offline

#13 2017-02-23 22:46:45

クイック
Guest

Re: Let関数でLoop処理を教えて下さい。

Let関数だけの本があればいいのにな。
Let関数は奥が深すぎませんか?

#14 2017-02-23 22:51:23

クイック
Guest

Re: Let関数でLoop処理を教えて下さい。

qb_dpさん、一度ファイルメーカー本(中・上級者用)を書いてくれませんか?
qb_dpさんは、C++でプラグインも作られていますし。
あなたの情報はのちのち必須になると思います。
年齢がわからないので、もしかしたら若かったら凄い人ですよ。
年寄りなら若い人に知識を与えましょうよ。

#15 2017-02-24 00:42:05

Hiro
Member

Re: Let関数でLoop処理を教えて下さい。

#10 wrote:

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

#16 2017-02-24 08:11:01

ぽんかん
Guest

Re: Let関数でLoop処理を教えて下さい。

初期化は必須ですよね。

スクリプト以外で使った場合の$変数のスコープは結構適当というか データビューアで定義しただけのでも次の計算まで残ってたりするし
バグじゃないならしっかり明記して欲しい。

#17 2017-02-24 09:37:01

honda
Guest

Re: Let関数でLoop処理を教えて下さい。

Let()で束縛する場合、種類とスコープと衝突にご注意を。
これも古いですが、今も通じる話のはず。

■ FileMakerの変数 寿命やスコープのおさらい | FileMakerを考える
http://filemaker-kou.seesaa.net/article/189610098.html

■ $ローカル変数の衝突の検証 | FileMakerを考える
http://filemaker-kou.seesaa.net/article/189903546.html

#18 2017-02-24 11:05:04

シャチ
Member

Re: Let関数でLoop処理を教えて下さい。

前に
Let($D=$D+1;$D)
の式を書いたのですが、
よく変数名に$がなくてもいいと書かれています。
また、リファレンスにも書かれています。

Let(D=D+1;D)
で、良いかと思うのですが、
これは 式の確定の段階で
フィールド名が見つからないとアラートが出ます。(FMP12段階)
この辺りは、なぜなのかがわかりません。
Let関数や変数だけの詳細のリファレンスがいるかもしれませんね。

Offline

#19 2017-02-24 11:38:20

ぽんかん
Guest

Re: Let関数でLoop処理を教えて下さい。

Dが定義されてないので参照できないですね。
$変数は、存在しない場合自動的に作られるけど、$なしのLet変数はLetの中でしか使えないのでLetで定義する必要がある。Let関数の外では参照できないので、全置換での連番の保存には使えません。

#20 2017-02-24 11:42:31

シャチ
Member

Re: Let関数でLoop処理を教えて下さい。

ぽんかん wrote:

Dが定義されてないので参照できないですね。
$変数は、存在しない場合自動的に作られるけど、$なしのLet変数はLetの中でしか使えないのでLetで定義する必要がある。Let関数の外では参照できないので、全置換での連番の保存には使えません。

この辺りの仕様は、理解するには難しすぎるんではと思ったりもしますね。
改めてリファレンスを読んで見たんですが、難解でした。

Offline

#21 2017-02-24 11:47:14

チポ
Member

Re: Let関数でLoop処理を教えて下さい。

例えば
  Let ( [ D = 0 ; D = D + 1 ] ; D )
これはOKですよね。

Offline

#22 2017-02-24 12:24:03

シャチ
Member

Re: Let関数でLoop処理を教えて下さい。

チポ wrote:

例えば
  Let ( [ D = 0 ; D = D + 1 ] ; D )
これはOKですよね。

しかし、これだと今回のような場合にはダメなんですよね
とにかく難しい仕様だと思います。

Offline

#23 2017-02-24 12:36:35

qb_dp
Member

Re: Let関数でLoop処理を教えて下さい。

「フィールド内容の全置換」の場合は、

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

#24 2017-02-24 12:44:10

ぽんかん
Guest

Re: Let関数でLoop処理を教えて下さい。

Let([D=Case(Get(レコード番号)=1;"";D); D=D+1]; D)
でもだめで、引き継げないという以前に式がエラーになります。
Dを定義し終わる前にDの代入式(右辺)にDを書くと、変数名でなくフィールド名(テーブル名)と解釈されます。

#25 2017-02-24 12:49:31

qb_dp
Member

Re: Let関数でLoop処理を教えて下さい。

あ~そうなんですね。
すみません。
Let([D=Case(Get(レコード番号)=1;"";D); D=D+1]; D)
は、未検証で書いてました。

Offline

Registered users online in this topic: 0, guests: 1
[Bot] ClaudeBot

Board footer

Powered by FluxBB
Modified by Visman

[ Generated in 0.010 seconds, 8 queries executed - Memory usage: 575.69 KiB (Peak: 612.59 KiB) ]