🧙

FileMaker 改行区切りリストから、行検索

2022/08/02に公開

「行抜きカスタム関数スピードコンテスト」の時に作ったヤツの解説。

https://twitter.com/fm0038queen/status/1551108876283817984?s=20&t=EyBYh7OAbgq67loHlFJQCg

ヒット数が多くてもそれなりのスピードで実行できます。

下記の例は、数行ですが、スピードコンテストのときは、4,000行くらい...
「1」を検索と言うお題が追加され、全行ヒットすると言う事に...
LOOPでは、遅くなるので、なんとかしてLOOP無しで出来ないかと考えたのが今回の計算式です。

対象
1017621|アースエコロコ
1002616|メイドインアース
1012036|アース製薬
1023218|ジル バイ ジルスチュアート
1000774|ジルスチュアート
1024198|シェアースピリット
1001659|アースミュージック
1022279|アークスタンダード
1024062|リムアーク
1001657|アークテリクス
検索ワード
アース
Let([ 
	~val = 行抜きカスタム関数の話::検索ワード
	;~str = 行抜きカスタム関数の話::対象
	;~char182 = "{c;h:a;r:1;8:2}" 
	;~str =Substitute ( ~str ; Char ( 182 ) ; ~char182 ) 
	;~str = Quote ( ~str ) 
	;~str = Middle ( ~str ; 2 ; Length ( ~str )-2) 
	;~formula =  
	"LET(~val=\"" & ~val & "\";" & 
	"LET(~str=\""  
	& 
	Substitute ( ~str ; Char ( 182 ) ;  
	"\";if(PatternCount(~str; ~val );~str & Char( 13 ))) & ¶LET(~str=\""  
	) 
	&  
	"\";if(PatternCount(~str ; ~val );~str))" 
	& ")"
	;~result = Substitute ( Evaluate ( ~formula )  ; ~char182 ; Char ( 182 )) 
]; 
	~result
)

改行マーク対策

対象に「¶」があるとエラーになるので、"{c;h:a;r:1;8:2}" に置換

;~char182 = "{c;h:a;r:1;8:2}" 
;~str =Substitute ( ~str ; Char ( 182 ) ; ~char182 ) 

Quote を適用し前後の「"」を削除

計算式内に挿入するため

;~str = Quote ( ~str ) 
;~str = Middle ( ~str ; 2 ; Length ( ~str )-2) 

元の文章の改行を計算式に置換

Quote を適用しているので実際には、 Char ( 182 ) を置換

;~formula =  
	"LET(~val=\"" & ~val & "\";" & 
	"LET(~str=\""  
	& 
	Substitute ( ~str ; Char ( 182 ) ;  
	"\";if(PatternCount(~str; ~val );~str & Char( 13 ))) & ¶LET(~str=\""  
	) 
	&  
	"\";if(PatternCount(~str ; ~val );~str))" 
	& ")"

~formula は、以下のようなFileMakerの計算式になります。

~formula
LET(~val="アース";
LET(~str="1017621|アースエコロコ";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1002616|メイドインアース";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1012036|アース製薬";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1023218|ジル バイ ジルスチュアート";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1000774|ジルスチュアート";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1024198|シェアースピリット";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1001659|アースミュージック";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1022279|アークスタンダード";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1024062|リムアーク";if(PatternCount(~str; ~val );~str & Char( 13 ))) & 
LET(~str="1001657|アークテリクス";if(PatternCount(~str ; ~val );~str))
)
上記式の1行抜粋

行ごとに PatternCount で判定

LET(
	~str="1017621|アースエコロコ"
	;
	if(PatternCount(~str; ~val );~str & Char( 13 ))
) & 

Evaluate で計算式を実行

Evaluate で計算式を実行し、~char182 を Char ( 182 ) へ置換
※ Char ( 182 ) = ¶

;~result = Substitute ( Evaluate ( ~formula )  ; ~char182 ; Char ( 182 )) 

文字数が多い場合の対応

4千行、30万文字くらいは、上記の式で問題ありません。
が、文字数が多くなるとエラーになります。(何文字でエラーになるかは未調査)

& より、Listで連結したほうがチョット速いのでListで連結と、
文字数が多い場合の対応で、1,000行づつ処理を行う式

Let([ 
	~str =& textToFilter &;~val = searchValue
	;~pCount = PatternCount ( ~str ; ~val ) 
	;~p = Position ( ~str  ; ~val ; 1 ; ~pCount ) 
	;~e = Position ( ~str  ;; ~p ; 1 ) 
	;~p = Position ( ~str  ; ~val ; 1 ; 1 ) 
	;~s = Position (Left ( ~str ; ~p ) ;; ~p ; -1) + 1 
	;~str = Middle ( ~str ; ~s ; ~e - ~s+1 ) 
]; 
While (  
    [  
	~count = ValueCount ( ~str )  
	;~n = 0 
	;~x = 1000 
	;~max = Ceiling ( ~count/~x ) 
	;~result = "" 
    ] ;  
    ~n    <    ~max ;  
    [ 
	~str1 = MiddleValues (  ~str ;  (~x*~n)+1 ; ~x )
	;~str1 = Replace ( ~str1  ; Length ( ~str1 ) ; 1 ; "" )
	;~result = List( ~result ;  
		Let([ 
			_val = ~val
			;_str = ~str1 & If ( PatternCount ( ~str1 ;) = 0 ;)
			;_char182 = "{c;h:a;r:1;8:2}" 
			;_str =Substitute ( _str ; Char ( 182 ) ; _char182 ) 
			;_str = Quote ( _str ) 
			;_str = Middle ( _str ; 2 ; Length ( _str )-2) 
			;_formula =  
			"LET(_val=\"" & _val & "\";" & 
			"¶list(¶LET(_str=\""  
			& 
			Substitute ( _str ; Char ( 182 ) ;  
			"\";if(PatternCount(_str; _val );_str));¶LET(_str=\""  
			) 
			&  
			"\";if(PatternCount(_str ; _val );_str))" 
			& "¶)¶)"
			;_result = Substitute ( Evaluate ( _formula )  ; _char182 ; Char ( 182 )) 
		]; 
			_result
		)

) 
	;~n = ~n+1 
    ] ; 
~result
) 
)

カスタム関数:

https://fm-aid.com/custom-function/39-containfiltervalues

Discussion