結論から言うと、現在のあなたの使い方(LLMに##タイトル付きのMarkdownを出力させ、Markdownコンバーターが##で自動的にシートを分割することを期待する)はDifyでは動作が保証されません。Markdownコンバーターには現在、##が必ずExcelのワークシート名になるという「公式に定められた」ルールがありません。
言い換えれば、
- MarkdownテーブルをExcelに変換することはできます。
- しかし、「複数シート + シート命名ロジック」は現在、比較的「ブラックボックス」であり、外部に文書化されたり、設定可能な機能ではありません。そのため、「Markdownは問題なさそうに見えるのに、
##でシートが分割されない」という現象は、現在の実装状況に合致しています。
以下に、どのように対処できるかについていくつか説明します。
1. 現在の挙動の理解
あなたが貼り付けた構造と合わせて:
{
"text": "## XXX\n\n| 列1 | 列2 |\n| --- | --- |\n| ... | ... |"
}
あなたの期待は:
## XXX→ ExcelにXXXという名前のシートが出現する## YYY→ 別のシートが新規作成される
しかし、現在のMarkdownコンバーターは、むしろ次のような挙動をします:
- Markdown全体を一つのドキュメントとして扱います。
- 「タイトル階層 → シート」ではなく、「テーブルそのもの」に重点を置いています。
そのため、よくある現象は次のとおりです:
- 1つのシートしか生成されない可能性があります。
- または、
##内のテキストではなく、デフォルトのシート名(例:Sheet1)が使用されます。
これはあなたのMarkdownの記述が間違っているのではなく、現在の製品設計において##が「シートの境界 + シート名」の正式なプロトコルとして扱われていないためです。
2. 「タイトルごとにシートを分割する」を実現するための検討可能なアプローチ
もし「##でシートを分割する」という強い要件がある場合、Markdownコンバーターのデフォルトルールを迂回し、「コードノード + Excelライブラリ」を使用して、目的の構造を明示的に複数シートとして書き出すことを検討できます。
アプローチ A:LLMが構造化JSONを出力し、その後コードでExcelを生成する
-
LLMノードでは、Markdownを直接出力させるのではなく、構造化JSONを出力させます。例えば:
{ "sheets": [ { "name": "SheetA", "table": [ ["列1", "列2"], ["a1", "a2"], ["b1", "b2"] ] }, { "name": "SheetB", "table": [ ["列1", "列2"], ["x1", "x2"] ] } ] } -
コードノード(Pythonを推奨)でこのJSONを解析し、
openpyxlやpandasなどのライブラリを使って自分でExcelを作成します。複数テーブル、複数シートを完全に制御できます。疑似コード例:
import io from openpyxl import Workbook import json data = json.loads(inputs["llm"]["text"]) # LLMの出力が上記のJSONであると仮定 wb = Workbook() # デフォルトシートを削除 default_ws = wb.active wb.remove(default_ws) for sheet in data["sheets"]: ws = wb.create_sheet(title=sheet["name"][:31]) # Excelシート名は最大31文字 for row in sheet["table"]: ws.append(row) # メモリに保存し、後続のノードにファイルとして返す buffer = io.BytesIO() wb.save(buffer) buffer.seek(0) outputs["excel_file"] = { "type": "document", "filename": "result.xlsx", "content": buffer.read() } -
その後、この
excel_fileを通常のファイルとしてユーザーにダウンロードさせたり、別のノードに渡したりすることができます。
利点:
- Markdownコンバーターの内部ルールに全く依存しません。
- シート名、シート数、各シートの内容をすべて自分で制御できます。
- LLMのタスクもより明確になります。「構造化計画」のみを担当し、Excelの詳細は担当しません。
アプローチ B:LLMに引き続きMarkdownを出力させ、コードで分割してからExcelを書き出す
もし現在のLLMプロンプトがMarkdown出力に固定されており、Markdownの可読性を好むのであれば、次のようにできます:
-
LLMに引き続き同様の構造を要求します:
## SheetA | 列1 | 列2 | | --- | --- | | a1 | a2 | | b1 | b2 | ## SheetB | 列1 | 列2 | | --- | --- | | x1 | x2 | -
ダウンストリームにコードノードを追加し、2つのことを行います:
- 正規表現 / Markdown解析ライブラリを使用して、テキストを
##タイトルごとにブロックに分割します。 - 各ブロック内の最初のテーブルを二次元配列として抽出し、その後上記と同様の方法でExcelの複数シートを書き出します。
例えば、シンプルな正規表現のアプローチ(疑似コード):
import re md = inputs["llm"]["text"] # 各シートのブロックに分割 blocks = re.split(r'^##\s+', md, flags=re.MULTILINE) # blocks[0]は##より前の内容である可能性があり、無視できます sheet_blocks = blocks[1:] sheets = [] for block in sheet_blocks: # 最初の行から改行前までがシート名 lines = block.splitlines() sheet_name = lines[0].strip() sheet_body = "\n".join(lines[1:]) # さらにsheet_bodyから最初のMarkdownテーブルを二次元配列として解析 # (自分でパーサーを書くことも、既存のライブラリを使うことも可能) table = parse_markdown_table(sheet_body) sheets.append({"name": sheet_name, "table": table}) # その後、上記のopenpyxlの書き込みロジックを再利用 - 正規表現 / Markdown解析ライブラリを使用して、テキストを
-
最終的には、Markdownコンバーターが自動的にシートを推測するのではなく、このコードノードがExcelを生成します。
3. もしMarkdownコンバーターに依存し続ける必要がある場合はどうするか?
現在入手可能な情報では、次のような「保証された」ドキュメントはありません:
##、###などの見出しとシート間のマッピングルール- または「タイトルごとにシートを分割する」を有効にするための何らかのスイッチ
したがって:
- たとえ現在、試行錯誤の結果「見出しごとにシートを分割できるらしい」という書き方を見つけたとしても、それは実装の詳細である可能性があり、将来のバージョンで安定するとは限りません。
- 本番環境では、未文書化の挙動に依存することを避けるため、上記の「LLM + コードによるExcel自作」の方法を推奨します。
4. 実践的なアドバイス(最小限の変更バージョン)
既存のワークフローで、大幅な変更をしたくない場合は、次のように微調整できます:
-
アップストリームLLM:
-
引き続き「
##付きのMarkdown」を出力させます。 -
ただし、プロンプト内でモデルに同時にJSONを出力する構造を保証させるように追加します。例えば:
先给我 Markdown 展示,方便阅读; 然后再给我一个 JSON 代码块,结构为: ```json { "sheets": [ { "name": "...", "table": [["表头1","表头2"],["...","..."]] } ] }
-
-
ダウンストリームにコードノードを新規追加:
- JSONの部分だけを読み込み、Markdownの部分は無視します。
- JSON → 複数シートExcelのロジックでファイルを生成します。
- Markdownコンバーターを使ってExcelに変換することはもうしません。
これにより:
- 人間がチャット履歴を見る際は依然として洗練されたMarkdownです。
- マシンがExcelに落とし込む際は、「構造化 + 制御可能」なパスを辿ります。
まとめ
- あなたが現在直面している問題の本質は、Markdownコンバーターに「
##→ Excelシート」という信頼できる、外部に公開されたルールがないため、期待するような方法で複数シートを作成しないということです。 - シート名と構造を安定して制御したい場合は、次のアプローチを推奨します:
- 「LLMが構造化JSONを出力 → コードノードがExcelを生成」;または
- 「LLMが
##付きのMarkdownを出力 → コードノードが##で分割 → 自分でExcelを書き出す」。
- これにより、内部の未文書化された実装の詳細に依存する必要がなくなり、将来のバージョンアップグレードもより安全になります。
もしよろしければ、現在のLLMの完全な出力例(匿名化後)を少し貼り付けていただければ、その出力を複数シートのExcelに変換するための対応するコードノードの例を直接作成できます。