2025年7月11日金曜日

QRcodeを生成する(APIは使わない)

 FileMakerでQRcodeを生成してみます。


テーブルは1個

フィールドはこれだけ。


「えっ!QRcodeを生成するテーブルとデータテーブルを分けないの?」
はい、分けません。
だって、生成側の源泉になるのがグローバルフィールドですし、リレーションやポータルのオーバーヘッドが無いし、スクリプトやレイアウトが1つのテーブル内で完結してるから印刷とか、後々一括生成とかも楽に作りたいから。


あと、APIも使いません。
それはPCやGOとかローカル環境も想定しているからです。(今回のは繋いだ状態)DCN方法はサンプルファイルに記載しています。

なによりもメンテが楽です。

今回は住所をQR化しています。

ダウンロード(win11,FMP19.6以降)
(すみません、デザインとか何も考えてません)



ということで、簡単な流れを書きます。


①JavaScriptのQRcode生成ライブラリを読み込む。もしくはDCNで埋め込む。

②①で生成させたQRは一時的にWebビューアーに表示させる。
(FileMakerでダイレクトにQRコードを画像化させることはできません)

DOM(ドム)Document Object Model側に描画された後にPNG化して画像として表示させる。(SVGやCanvas化されたものをBase64形式に変換する)






①JavaScriptのQRcode生成ライブラリを読み込む。もしくはDCNで埋め込む。
についてですが、ローカルで使う場合は読込先のコードをまるっきし埋め込んで使ってもよいと思います。

で、今回のqr-code-stylingという読込先。
FileMakerとの相性はいい方だと思いますよ。

昔からある GitHub: davidshimjs/qrcodejs については
もう少しJavaScriptの知識が無いとFileMakerとの連携が難しいです。

JavaScript側に「FileMakerへの指示(スクリプト呼び出し)」を明示的に組み込まないと、FileMakerとの連携は行われません。Base64変換も FileMakerへのデータ返却もなにもされないので、JavaScript側からFileMaker側に引数を取らせてLOOPさせるとか、けっこう大変です。

工数ばかりかかるし、レイアウトをまたぐと意外と厄介だったりするので、同テーブルにqr-code-stylingなら20分作業!みたいな感じでいいのかと思います。




DATA::g_QRテンプレートHTML

これにhtmlを入れます。htmlの中身は省略します。
サンプルにはJavaScriptのコメント入れてありますのでご参考に。



Webビューアーには

DATA::g_住所QR

これだけ入れておきます。




g_QRテンプレートHTML
(これにhtmlの中身を入れておく)

FileMakerのスクリプトで

DATA::g_住所QRg_QRテンプレートHTMLの中身を渡す。
webビューアーに表示させる。
Base64でPNG画像に変換してWebビューアーの表示を消す。


ここでFileMaker側のスクリプトは2つ必要となります。

QR_webビューアーに表示



qrcode (JavaScript側で動かすのでスクリプト名は変えないように)



QR_webビューアーに表示について
今回は住所をQR化しているので、QRを読み込んだ後、GoogleMAPで開きます。



FileMaker側のスクリプト


変数を設定[$mapURL;値:

Substitute (

    "https://www.google.com/maps?q=" & GetAsURLEncoded ( DATA::住所 ) ;

    "'" ; "%27"

  )]

"%27"は 16進数でのASCIIコード 0x27 = 10進数で 39
ASCIIコード 39番は → シングルクォート '


大事なのはスクリプト内の
変数を設定[ $html ; 値 : Substitute ( $template ; "<<MAP_URL>>" ; $mapURL )]
ですね。


これはg_QRテンプレートHTML内の"<<MAP_URL>>"をFileMaker側の住所データに置き換えているってことです。


<<MAP_URL>>
FileMakerなどでスクリプトから置換されるプレースホルダの事です。



しかし、本来は

DATA::g_QRテンプレートHTML内に

htmlのbody内でいうと

  <div id="qrcode"></div>


  <script>

    const qr = new QRCodeStyling({

      width: 300,

      height: 300,

      data: "", // ← 初期データは空(doItからセット)

      image: "",

      dotsOptions: { color: "#000", type: "square" },

      backgroundOptions: { color: "#fff" },

      qrOptions: { errorCorrectionLevel: "L" }

    });


    function doIt(mapURL) {

      // URLをセットしてQRコード更新

      qr.update({ data: mapURL }); //ここで遅くなる


      // QRコード描画(1回のみ)

      const target = document.getElementById("qrcode");

      target.innerHTML = ""; // ← 再生成時の二重描画防止

      qr.append(target);


      // 少し待って画像として取得 → FileMakerに渡す

      setTimeout(() => {

        qr.getRawData("png").then(blob => {

          const reader = new FileReader();

          reader.onloadend = () => {

            const base64data = reader.result.split(",")[1];

            if (window.FileMaker) {

              FileMaker.PerformScript("qrcode", base64data);

            }

          };

          reader.readAsDataURL(blob);

        });

      }, 300);

    }

  </script>


にするのですが、
ちょっと処理が遅く感じます。

qr.update({ data: xxx })は、一度オブジェクトが生成された後に、値を書き換えて、再描画して〇〇という処理になるので、任意のタイミングをとってQR変換させるにはいいけど、一回っきりの<<MAP_URL>>にした方がダイレクトで処理は速いし、一括でLOOP発行させるときも楽。FileMakerっぽくて好きかなと。




なので、html全文

<!DOCTYPE html>

<html>

<head>

  <meta charset="utf-8">

  <title>QR</title>

  <script src="https://cdn.jsdelivr.net/npm/qr-code-styling@1.5.0/lib/qr-code-styling.js"></script>

</head>

<body style="margin:0;display:flex;justify-content:center;align-items:center;height:100vh;">

  <div id="qrcode"></div>

  <script>

    const qr = new QRCodeStyling({

      width:300,

      height:300,

      data: "<<MAP_URL>>",  //ここにダイレクトにデータを読み込ませ

      image: "",

      dotsOptions: { color: "#000", type: "square" },

      backgroundOptions: { color: "#fff" },

      qrOptions: { errorCorrectionLevel: "L" }   // LとかMとかHとか

    });


    qr.append(document.getElementById("qrcode"));


    // Base64エクスポートしてFileMakerに渡す

    setTimeout(() => {

      qr.getRawData("png").then(blob => {

        const reader = new FileReader();

        reader.onloadend = () => {

          const base64data = reader.result.split(",")[1];

          if (window.FileMaker) {

            FileMaker.PerformScript("qrcode", base64data);

          }

        };

        reader.readAsDataURL(blob);

      });

    }, 500); // SVG生成完了後に画像化

  </script>

</body>

</html>




FileMaker側のスクリプトにも最後に
Web ビューアで JavaScript を実行 [ オブジェクト名: "Web" ; 関数名: "doIt" ; 引数: $mapURL ]
を入れています。

関数名: "doIt" を入れておいてもqrオブジェクトの初期化時にすでに済んでいるのでエラーにはならず条件付きで動くんです。
関数名: "doIt" は動いていないけど、取ってしまうと全く動かなくなる。

早い処理にするために"doIt" など明示的な意味合いで使用しています。



サンプルですが、グローバルフィールド内のhtml文が丸ごと消えていたら

下に「万が一html復活」というボタンを用意しましたので復活してください


2025年7月3日木曜日

なんでこうなった。FileMaker

 FileMaker(現Claris)が公式に開発者数を発表していたのは古く、2012年頃の国内アクティブライセンス数はざっくり10万本台後半(正規ユーザー数はもっと少ない)らしいけど、その後の公開は途絶えているみたい。Claris Partner数(旧FBA認定開発者)が国内でピーク時は400社以上あったようだけど、2024年時点では公式サイトで確認できるのは200社弱に減少している。ここから開発に関わる企業数自体が半減したのはほぼ確実。

国内の求人情報では2015年頃には「FileMaker経験者歓迎」の求人が一定数あった気がするけど、2020年代に入ってからは大手求人サイトで「FileMaker」の単独求人はほぼ見なくなった。

一番大きな原因は、ワクワク感よりライセンス増を選んだことかな。かつてWeb開発者がFileMakerに参加できる大きな窓口だったPHP APIが、WPEの終息で将来的に使えなくなる流れになり、米国のWeb系エンジニアがFileMakerから相当離れた。

更にはWebビューアーのレンダリングの限界

WebビューアーはFileMakerのレイアウト内にWebページを表示するオブジェクトだが、複雑なJavaScriptや大量のDOM操作を伴う場合、処理が追いつかなくなることがある。
たとえば、FileMakerのリストで「データが大量過ぎてスクロールも出来ない、スクロールがリセットされてしまう、迷子になる」など長年悩まされ続けている。解決させるためにAG-gridなどを使ってみてページングさせようと試みるが、少ないデータならWebビューアーは表示するも、大量だとブラウザのメモリや処理能力の限界に達する。なのでこちら側で最適化を考える。Data APIの年間使用量上限が廃止されたことで、大量データの活用が容易とあるが、必要なデータのみをJSON形式で効率的にWebビューアーに渡さない限り、結果は同じと言う事。
WebビューアーがデータベースのDATAに向いていない事が明らかになった時のガッカリ度は半端なかった。


それ以降見事に減っている。

・たてまえは、Webアプリやクラウドシステムがビジネスの主流になり、FileMaker単体では対応が難しい要件が増えた。特にスマホ・ブラウザ対応を望まれる中、FileMakerはWebDirectやCWPで頑張っていたけど、技術的・ライセンス的制約が多く、WebエンジニアがわざわざFileMakerを学ぶメリットが薄れたのだという。SaaSとの競合で負けてるってのもあるけど・・・。今はSaaS(Software as a Service)で「ある程度カスタマイズできるクラウドサービス」が続々と登場してるし、社内でなんとかする風潮もある。

FileMaker認定とか、まったくお客と関係の無い事に捕らわれ、気が付いたときはエンドユーザーが離れたという事じゃないのか。極端な話、お客はFileMakerだろうが、SQLだろうがDelphi(古)だろうが目的が達成できればいいわけだ。余計な縛りが増えてくると簡単に「別のもの」に切り替える。そこを素直に認めない開発者集団になるのは危険だ。ただ救いは経営陣が金融系ではなく技術畑で成り立っていること。


・本音の原因はライセンスが高い。これに尽きる。
同時接続数を厳しく制限するライセンス体系や、クラウド版(Claris FileMaker Cloud)への移行を推奨する戦略により、中小企業ユーザーや個人開発者がFileMakerを導入しづらくなった。以前の「FileMaker Pro単品を1本買って小規模運用」ができなくなったのも大きい。

以前なら、アドバンス1個あれば大抵の開発はできたけど、今はサーバーとクライアント5のライセンスを更新してる感じだから負担が大きいし、フリーの開発者が離れる原因を作ったのは間違いないかな。そして学生さんも使わなくなった。

Are businesses still relying on FileMaker Pro?


Crazy expensive?

“Yes FileMaker has gotten very expensive for small businesses. It’s because Claris… focus on businesses in the 100-1000 user range… For ~5 licenses it’s stupidly expensive compared to the competition. And Claris has spent the past ten years steadily working to ensure that every penny that can be squeezed out of their stagnant user base is duly squeezed out.”


“FileMaker has just fallen way too far behind the competition. I’m embarrassed I didn’t retrain earlier… My company has decided to completely switch to Salesforce.”


ただの拾った声だけど、本音だよ。昔はユーザーとの距離が近かったけど、このまま放置したらマズイ状況にあるのは間違いないと思う。


僕も肌で感じている。
91年に初めてFileMakerPro2を使用したときに、「プレビュー!」だけで驚き、レイアウトのフィールドも直感で動かせ、繰返しフィールドで飯が2杯おかわり出来た時代。こうしなきゃダメだよなんて言う人も居なかったし、直感で好きになれた。パソコン通信で海外のテンプレートを開くとほとんど医療系だったこと。Pro3でリレーション!でも中途半端なリレーションで4になってリレーショングラフが作れたんじゃなかったっけ?その後変数が使えるようになり、ランタイム作れたりワクワク感もあった。
でも、感じたことはインターネットの普及とともにFileMakerとユーザーの距離がどんどん遠くなっていく。


「インターネットは危険です!」
「クラウド依存は危険です!」の時代になったらFileMakerは強いかも。
完全スタンドアロンで業務アプリを作って完結できるシステムって今考えると凄いけど、ExcelやAccess、桐なんかもそう。Delphi系、MAC好きおフランス系の4th Dimensionなんかもそうか・・・。

真面目な話、拠点が少ない中小企業の業務用ソフトで、そもそもクラウドの必要性を疑う人もけっこういるし、サイバー攻撃やクラウドサービス提供会社の一方的な利用規約変更や値上げに腹立っている人も多いから、全ての道が途絶えるわけじゃないけど、負担のことを考えるとSaaSに移る事業者が増えてるのを実感してる。



僕は続けるけどねw





2025年6月17日火曜日

JT00000001を「JTスぺ-ス1とかで検索したい!」という人のために


「JTスぺ-ス1とかで検索したい!」

とかいう人のために。

--------------------------------------------------------------

計算フィールの結果(テキスト)

J
JT
JT0
JT00
JT000
JT0000
JT00000
JT000000
JT0000000
JT00000001


T
T0
T00
T000
T0000
T00000
T000000
T0000000
T00000001


0
00
000
0000
00000
000000
0000000
00000001


0
00
000
0000
00000
000000
0000001


0
00
000
0000
00000
000001


0
00
000
0000
00001


0
00
000
0001


0
00
001


0
01


1


-----------------------------------------------

計算式フィールドの中身


AllSubstrings ( 商品No )


(テキスト)非保存にしないでねw

-------------------------------------------------

「ホレ、なんもかんもバラバラにしちゃいなさいや!」というカスタム関数を3つ作るのさ。

なんもだから・・・


-----①関数------

関数名:AllSubstrings
引数:str


/*----------------------------------------------------------*/

Let (

  [

    len = Length ( str )

  ] ;


  If ( len = 0 ; "" ;

    SubstringFrom ( str ; 1 ) & ¶ & AllSubstrings ( Middle ( str ; 2 ; len - 1 ) )

  )

)


/*---------------------------*/




-----②関数----再起処理-----

関数名:SubstringFrom
引数:str;start;


/*----------------------------------------------------------*/

If ( start > Length ( str ) ; "" ;

  Let (

    [

      acc = ""

    ] ;


    Let (

      [

        end = Length ( str ) ;

        result = RecursiveJoin ( str ; start ; start )

      ] ;


      result

    )

  )

)


/*---------------------------*/




-----③関数------

関数名:RecursiveJoin
引数:str;start;current


/*----------------------------------------------------------*/

If ( current > Length ( str ) ; "" ;

  Left ( str ; current ) & ¶ & RecursiveJoin ( str ; start ; current + 1 )

)

/*---------------------------*/


わやだぁ












コード番号のあいまい検索 カスタム関数作るべさ。

 凄く長く放置してました。3年放置?

FileMaker止めてたわけじゃないんですよ。以前みたいにマメじゃなくなっただけです。

そう!長野に移住したんです。

理由は、夏が暑くなったから!これしかない

マックスのお散歩でアスファルト47℃とかさ、もーおかしいでしょ東京。
それで八ヶ岳の麓の標高800mの町にフルリフォームの家に住んでます。
土地合わせて300㎡だよ。住宅ローンは20年で東京の家賃の半分以下。
まじです。
ワンワン走り回ってます。
仕事はそのまま東京の某会社の下請け侍やってます。
実家の帯広に帰れよ!って話なんだけど、ほら蛍飛んでるし、こっち。

足りなくなったんでどなたか仕事ください。


で、本題。
なんか最近同じような開発案件が続いたんでカスタム関数にするべ!と思って
作っちゃいました。


商品マスタのCDとかで「NB00000001」とか、え?まだそんな感じなんだっていうのあるでしょ?

それでこれをあいまい検索できるようにして!とか依頼来るんですよ。
ゼロ何回も打ってられないので、商品CDとは別に計算フィールドを作ります。


1
01
001
0001
00001
000001
0000001
00000001
B00000001
NB00000001

テキスト改行の計算式を作るわけ。
よくやってたじゃないですか昔・・・左から・・・

外人さんの名前とか便利だったし。

でも、今回のはCDなので右端から改行させます。



関数名:IncrementFromRight(なんでもいいんだけど)
引数:str


/*------------------------中身------------------------*/


Let ( [

    len = Length ( str )

] ;


    If ( len = 0 ;

        "" ;

        Let ( [

            part = Right ( str ; len ) ;

            rest = IncrementFromRight ( Right ( str ; len - 1 ) )

        ] ;

            Case (

                IsEmpty ( rest ) ; part ;

                rest & ¶ & part

            )

        )

    )

)



/*----------------------------------*/


で、検索 

1でも

01でも

001でも

ヒットしますよーって話。




ちなみに左は

関数名:IncrementFromLeft

引数:str

/*-----------------------------------------------*/


Let ( [

    len = Length ( str )

] ;

    If ( len = 0 ;

        "" ;

        Let ( [

            part = Left ( str ; len ) ;

            rest = IncrementFromLeft ( Left ( str ; len - 1 ) )

        ] ;

            Case (

                IsEmpty ( rest ) ; part ;

                rest & ¶ & part

            )

        )

    )

)

/*----------------------------------*/



名前とかに使用するといいよね。










QRcodeを生成する(APIは使わない)

  FileMakerでQRcodeを生成してみます。 テーブルは1個 フィールドはこれだけ。 「えっ!QRcodeを生成するテーブルとデータテーブルを分けないの?」 はい、分けません。 だって、生成側の源泉になるのがグローバルフィールドですし、リレーションやポータルのオーバーヘ...