FileMakerでナレッジDBをつくるよ!Part 1
社内ナレッジDBを作成する
社内ナレッジを作ろうと思い続けて6ヶ月ほど、
色々な可能性を検討しました。
最終的には、資料横断型のRAGをローカルで構築したかったのです。
例えば、Pythonで今まで作成した資料をベクトルDBに登録し、
セマンティック検索ができるようにとか。
OneNoteでナレッジを作成してその内容を公開しようとするとか。
どちらも保守性に難がありました。
作成はできるかもしれないが、今後の変更や保守をどのようにするのか?
私が居なくなった後でも使用できるのか?
それらが分からなく踏み出せませんでした。
Pythonは作成自体が複雑になり、現状の私の手に余るものでした。
OneNoteは非常に作成が簡易なインターフェースで記事を作成できます。
取り込んだ画像もOCRでテキストを抽出、検索することができます。
これらの記事ををチャンク化、ベクトル化することで、
RAGシステムにしたかったのです。
しかし、Web版のOneNoteはデータ移行ができないということになり、
もし問題が発生、もしくは、システムが変わった時に対応できなるのではないかと思いました。
そんな時、天啓が降りました。
「FileMakerで作成すればいいではないか!」と。
ここで少し、FileMakerについて触れておきます。
FileMakerは、データベースを土台にして、
入力画面・一覧画面・検索・帳票・ボタン処理などをまとめて作れる、
ローコード寄りの開発ツールです。
顧客管理や問い合わせ管理、業務記録のような「現場で使う仕組み」を、
比較的すばやく形にできるのが特徴です。
まず動くものを作り、使いながら改善していく。
そういった内製開発と相性がよく、
私自身も6年ほどFileMakerでシステム構築をしてきました。
そのため、今回の社内ナレッジDBでも、
「作れるか」だけでなく
「あとから直せるか」
「自分がいなくなっても保守できるか」を考えたとき、
非常に相性がよいと感じたのです。
私がいいと思っていたのはHTMLを編集できるOneNoteのUIでした。
それらはFileMakerをJavascriptで拡張すれば可能ではないかと思ったのです。
今回から、FileMakerナレッジシステムの作成を連載で
お伝えしたいと思います。
私は6年間ほど、FileMakerでシステム構築をしていた経験があるため、
一番触りやすいというのがありました。
FileMakerに需要はあるのか!?
分からないのですが、ちょっと発信してみたいと思います☺️✨
最後に生成物をダウンロードできるようにしているのですが、
そこの部分は有料にしようと思います!
拡散で無料にしているので
ご興味あれば、拡散もおねがいいたします😌
それでは、ナレッジをHTMLエディタで記入できるようにしたいと思います!
まずはFileMakerのテーマを決めよう!
テーマについては、上記の記事に分かりやすく記載されています。
これ以外にもネットを探したらテーマがあると思います。
FileMakerにはテーマというのがあり、
それを設定すると簡単に全体のテーマカラーやフィールドの形状、
フォント、ボタンを整えることができます!
テーマ1つで画面のイメージが変わってきますので、最初にイメージを掴むのが大切です。
TinyMCE Community をダウンロード
取り敢えず、無料HTMLエディタを組み込んで
記入できるようにしましょう。
今回は TinyMCE の無料HTMLエディタを
FileMakerに組み込みたいと思います。
TinyMCE は Javascriptで記載されております。
下のリンクをクリックしてください。
上のボタンをクリックすると TinyMCE をダウンロードできます。

下に同じものを保存しました。
TinyMCEのライセンスは LGPL v2.1 です。
社内利用、社用利用、組み込み可能なライセンスです。
# Software License Agreement
**TinyMCE** – [<https://github.com/tinymce/tinymce>](https://github.com/tinymce/tinymce)
Copyright (c) 2024, Ephox Corporation DBA Tiny Technologies, Inc.
Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
tinymce_8.3.2.zip を解凍しなかにある、tinymce フォルダを
C:\\Users\あなたのユーザ名\
の下に保存してください。
今回はローカル環境で動作するところまで目指します。


FileMakerにHTMLエディタを追加しよう!
テーブル構造の作成から
まず、Masterテーブルを作成し、そこにJavascriptの内容をコピーします。

もしくは、Ctrl + Shift + D で開きます。



knowedgeDBテーブルに _1_G フィールドを追加
オプション指定




(つなぎたいフィールドをドラッグ&ドロップで結ぶとリレーションがはれます)


これで Master テーブル の値が knowledgeDB テーブルから
参照できるようになりました。
・・・
💡TIPs:なぜこのようなリレーションにしたのか?
今回、MasterテーブルとkowlegeDBテーブルでリレーションを張りました。
どちらも、1 の値になります。
Masterテーブルは1レコードしかないのでkowlegeDB からはどのレコードでも同じレコードが参照できるようになります。
今回、フィールドの設定を別にしていました。
Masterテーブルは計算フィールドで 1 を持たし、
kowlegeDBテーブルは グローバルフィールドにして1を持たせました。
なぜ、このように設定したかというと、kowlegeDBが0レコードでも、Masterテーブルの値を参照できるようにしたかったからです。

どちらも同じ用に計算フィールドにしてしまうと、kowlegeDBが0レコードの場合にMasterの値を参照できず、思わぬバグの温床になることがあります。
今回の運用ではあまり意味はないかもしれませんが、バグが少なくなるようなクセをつけています。
FileMakerのグローバルフィールドはクセがあり、ローカルか共有かで挙動が変わってきます。
起動時に実行するスクリプトでグローバルフィールド(今回で言えばkowlegeDB::_1_G に 1 を格納するようにしましょう。
・・・
WebビューアでHTMLエディタを参照しよう

タイプ:テキスト
1) マスターに入れる「テンプレHTML」
Master::EditorTemplateHTML にこれを丸ごと保存:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
%%TINYMCE_SCRIPT%%
<script>
const b64ToUtf8 = (b64) => decodeURIComponent(escape(atob(b64)));
window.__initialHtml = b64ToUtf8("%%CONTENT_B64%%");
function fmSave(){
try{
FileMaker.PerformScript("SaveHTML", tinymce.get("editor").getContent());
}catch(e){}
}
%%INIT_JS%%
</script>
</head>
<body>
<textarea id="editor"></textarea>
</body>
</html>
2) Masterの「ScriptTag」と「InitJS」
A) TinyMCE本体の読み込み(Master::TinyMCE_ScriptTag)
今回は実験のため、ローカルで実装します。
(最終的にはWebサーバに上げる予定)
Master::TinyMCE_ScriptTagに以下を設定します。
<script src="%%TINYMCE_SRC%%"></script>B)init設定(Master::TinyMCE_InitJS)
Master::TinyMCE_InitJS にこれを設定します。
tinymce.init({
selector:'#editor',
height:600,
base_url: '%%TINYMCE_BASE%%',
suffix: '.min',
setup:(ed)=>{
ed.on('init', ()=>{ ed.setContent(window.__initialHtml || ""); });
ed.on('change keyup', ()=>{ fmSave(); });
}
});
3) WebViewerの計算式(ここが“組み込み”本体)

KowlegeDBのレイアウトで
WebViewerの「計算によるWebアドレス」に以下を入れます:
Let ([
template = Master::EditorTemplateHTML ;
// fmp12と同じフォルダを file:///... に変換
fp = Get ( FilePath ) ;
dir = Left ( fp ; Position ( fp ; "/" ; -1 ; 1 ) ) ;
base =
Case (
Left ( fp ; 7 ) = "filewin" ; Substitute ( dir ; "filewin:" ; "file:///" ) ;
Left ( fp ; 7 ) = "filemac" ; Substitute ( dir ; "filemac:" ; "file:///" ) ;
dir
) ;
// tinymceの場所(同階層に tinymce フォルダがある前提)
tinymceBase = base & "tinymce" ;
tinymceSrc = tinymceBase & "/tinymce.min.js" ;
// MasterのScriptTag/InitJSに差し込み
scriptTag = Substitute ( Master::TinyMCE_ScriptTag ; "%%TINYMCE_SRC%%" ; tinymceSrc ) ;
initJs = Substitute ( Master::TinyMCE_InitJS ; "%%TINYMCE_BASE%%" ; tinymceBase ) ;
contentB64 = Base64Encode ( TextEncode ( knowledgeDB::HTML_Content ; "UTF-8" ; 1 ) ) ;
html = Substitute ( template ;
[ "%%TINYMCE_SCRIPT%%" ; scriptTag ] ;
[ "%%INIT_JS%%" ; initJs ] ;
[ "%%CONTENT_B64%%" ; contentB64 ]
)
] ;
"data:text/html;base64," & Base64Encode ( TextEncode ( html ; "UTF-8" ; 1 ) )
)


成功しませんでしたね。よくあることです。
デバッグ
確認すると、以下のような状況でした。
Webビューアで data:(data:text/html;base64,…)としてHTMLを開くと、そこから file:///... のJS/CSS等(tinymce.min.js や skins/css)を読み込むのがブラウザ側(WebView2/Edge)のセキュリティ制約でブロックされやすいです。
結果として tinymce が読み込まれず init も走らない →「起動してない」状態になります。
解決策: HTML自体も file:/// で開く(data: をやめる)
TinyMCE一式を置いたのと同じ階層に editor.html を1個置いて、Webビューアはそれを開きます。
(同一オリジンが file: になり、TinyMCEの追加リソース(skins等)も読み込める可能性が上がります)
1) editor.html(例)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="./tinymce/tinymce.min.js"></script>
<script>
function b64ToUtf8(b64){
// BOM対策も兼ねて安全寄り
const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
return new TextDecoder("utf-8").decode(bytes);
}
function getParam(name){
const u = new URL(location.href);
return u.searchParams.get(name) || "";
}
window.__initialHtml = b64ToUtf8(getParam("b64"));
function fmSave(){
try{
FileMaker.PerformScript("SaveHTML", tinymce.get("editor").getContent());
}catch(e){}
}
tinymce.init({
selector:'#editor',
height:600,
// base_url は「tinymce.min.js があるフォルダ」を指す(ここ超重要)
base_url: './tinymce',
suffix: '.min',
setup:(ed)=>{
ed.on('init', ()=>{ ed.setContent(window.__initialHtml || ""); });
ed.on('change keyup', ()=>{ fmSave(); });
}
});
</script>
</head>
<body>
<textarea id="editor"></textarea>
</body>
</html>
2) FileMaker Webビューア計算(editor.html を開く)
b64 はURLクエリに載せるので GetAsURLEncoded を挟みます。
Let ([
fp = Get ( ファイルパス ) ;
dir = Left ( fp ; Position ( fp ; "/" ; -1 ; 1 ) ) ;
base =
Case (
Left ( fp ; 7 ) = "filewin" ; Substitute ( dir ; "filewin:" ; "file:///" ) ;
Left ( fp ; 7 ) = "filemac" ; Substitute ( dir ; "filemac:" ; "file:///" ) ;
dir
) ;
contentB64 = Base64Encode ( TextEncode ( knowledgeDB::HTML_Content ; "UTF-8" ; 0 ) ) ;
b64q = GetAsURLEncoded ( contentB64 ) ;
url = base & "editor.html?b64=" & b64q
] ;
url)
※ TextEncode 第3引数は 0(BOMなし)推奨。BOMが混じると先頭に変な文字が入って挙動が怪しくなることがあります。

うまくいかない。
そもそも、editor.htmlが動いているか?

editor.htmlにライセンスが必要
tinymce.init に以下の1行を追加する必要がある
license_key: 'gpl',editor.html(改)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="./tinymce/tinymce.min.js"></script>
<script>
function b64ToUtf8(b64){
// BOM対策も兼ねて安全寄り
const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
return new TextDecoder("utf-8").decode(bytes);
}
function getParam(name){
const u = new URL(location.href);
return u.searchParams.get(name) || "";
}
window.__initialHtml = b64ToUtf8(getParam("b64"));
function fmSave(){
try{
FileMaker.PerformScript("SaveHTML", tinymce.get("editor").getContent());
}catch(e){}
}
tinymce.init({
selector:'#editor',
height:600,
// base_url は「tinymce.min.js があるフォルダ」を指す(ここ超重要)
base_url: './tinymce',
license_key: 'gpl',
suffix: '.min',
setup:(ed)=>{
ed.on('init', ()=>{ ed.setContent(window.__initialHtml || ""); });
ed.on('change keyup', ()=>{ fmSave(); });
}
});
</script>
</head>
<body>
<textarea id="editor"></textarea>
</body>
</html>
キーを入力することで、editor.htmlを直接開き編集することができるようになりました。
FileMakerから開けなかったですが、パスを直接指定すると開けることが判明しました。
そのため、Webビューアの計算式を以下のように変更して無事、FileMakerでも開けるようにできることを確認しました。
Let ([
fp = Substitute ( Get ( ファイルパス ) ; "\\" ; "/" ) ;
// 最後の "/" の位置
p = Position ( fp ; "/" ; Length ( fp ) ; -1 ) ;
// フォルダまで(末尾 / を含む)
dirRaw = Left ( fp ; p ) ;
// file:/C:/... → file:///C:/...
dir = Case (
Left ( dirRaw ; 6 ) = "file:/" and Left ( dirRaw ; 8 ) ≠ "file:///" ;
"file:///" & Middle ( dirRaw ; 7 ; Length ( dirRaw ) - 6 ) ;
dirRaw
);
contentB64 = Base64Encode ( TextEncode ( knowledgeDB::HTML_Content ; "UTF-8" ; 0 ) ) ;
b64q = GetAsURLEncoded ( contentB64 ) ;
URL = dir & "editor.html?b64=" & b64q
] ;
URL
)
ようやく、FileMaker上で表示することができました!

結局せっかく作った「Master」テーブルは使わず、
ローカルにあるhtmlを読み込んで完成でした。
画像挿入は私がほしかった機能なので、
Webで実装した方が良さそうです。
FileMakerのDataAPIで書き込むようにしましょうかね。
システム開発は難しいですね💦
まとめ
今回は取り敢えず、JavaScriptのHTMLエディタがFileMakerで動作することを確認しました。
次回は、以下を確認していきたいです。
FileMaker Serverへの移行(Data APIはどれくらい使える?)
WebDirectなら画面が貼り付けられるのか?
WebブラウザからFileMakerへの書き込み&読み込み(Data API)
よろしくお願いします☺️
いちごいぬ🐶
⏬️次回の記事
#FileMaker #社内ナレッジ #ナレッジベース #ナレッジマネジメント #業務改善 #社内DX #情報整理 #ドキュメント管理 #FAQ #RAG #生成AI #ローカルLLM #ベクトルDB #セマンティック検索 #OCR #OneNote #Python #TinyMCE #JavaScript #WebViewer #WebView2 #DataAPI #FileMakerServer #WebDirect #システム設計 #保守運用 #内製開発 #検証ログ #連載企画
今回の生成物
以下からダウンロードできます☺️
ご利用前に、免責事項と利用条件をご確認ください。
Tinymceは含まれていませんので、README.txtを確認し、
同じフォルダ構造になるように配置してください。
免責事項
本データは、個人または所属組織内での利用を前提として公開しています。著作権は作者に帰属します。
無断での再配布、販売、改変後の配布・販売、作者の許可のない第三者提供は禁止します。
本データは現状有姿で提供しており、動作保証・完全性・特定目的への適合性は保証しません。
本データの利用または利用不能により生じた損害について、作者は一切の責任を負いません。
同梱または関連する第三者ソフトウェアには、それぞれのライセンスが適用されます。
いいなと思ったら応援しよう!
ゆるこみの活動に賛同いただけましたら、応援いただけると大変励みになります!
その一歩で、ゆるやかなつながりを育てていきます 🍀