21
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

古のMS-OfficeファイルをSnowflakeであれこれしてAI-Readyにしたい

21
Last updated at Posted at 2025-10-04

最近Snowflakeで仕事していることの多いこのごろです。

わけあってdocファイルとかxlsファイルとかpptファイルが大量にでてきたけど、これ読み込めないじゃんと困ってていろいろ調べたまとめです。

なにができたらうれしいか

とりあえずいろんな文書をMarkdownにしたい。最近はSnowflakeでもAI Parse Document関数によってスキャンして画像しかないPDFだろうが表まで認識してMarkdownにできるようになってきており(前はAzure Document Intelligenceくらいしかいいのなかった記憶)、これで処理できる形式になってれば勝ちです。

で、

許可されたファイルタイプ
PDF 、 PPTX 、 DOCX 、 JPEG 、 JPG 、 PNG 、 TIFF 、 TIF 、 HTML 、 TXT

とのことなので、神Excelや古のdoc, ppt, xlsなんかはこのままじゃいけないのです。ここに書いてある形式になれば、ほぼ勝ちです。

やったこと

  1. LiberOfficeのヘッドレスで変換
  2. これのDocekr化
  3. SPCS化

この流れです。これでSnowflakeのステージに上がってればまとめて変換できます。神エクセルも一回PDFにしちゃうので大丈夫です。

LiberOfficeのヘッドレスで変換

doc to docxなどをいろいろ調べた結果、割とみんな苦労しているみたいですが(これとかほかにも引用したい記事いくつもあったけどメモってないので二度と見つからない…)、調べてくと、Liber Officeのヘッドレスモードで変換できるということを発見。

わかれば無限に記事がでてきます

というわけでUbuntu環境でためしてみたら超簡単にできました。

Liber Officeで開ければなんでもいいので、xlsもdocもpptもいけちゃう。感動。
xlsxからpdfもいけちゃいます。

soffice --headless --convert-to "docx" file.doc

こんな簡単なコマンドで変換できてしまします。

別解として手作業だったらブラウザ版のOfficeで読み込んでダウンロードしてもよさそう

これのDocekr化

最終的にはSnowflake上で動かしたいです。さすがにLiber Officeは標準ではいってないので、Snowpark Container ServicesでJOBとして動かすことを目指します。SPCSは端的に言えばSnowflakeマネージドなk8sなのでdocker imageにさえしてしまえばほぼ何でもできます。詳細はこの記事とかどうぞ。

Liber Officeはいったイメージ、どれがいいのかよくわからなかったのであきらめてDebianからaptしていきます。この辺はもうChatGPT先生がなんとかしてくれる。

というわけでコードはこちらにあります。

Excelがpdfにしたときに横がはみ出て(いつものあれです)、しかもその状態のpdfでAI_PARSE_DOCUMENTしたらハルシネーションしやがったので調整しました。

SPCS化

つくったDockerfileをSnowflakeのレポジトリに流し込んでSPEC書いてEXCUTE JOBするだけ。pipではいるsnowflake-cliを使わないとレポジトリに流し込めないという。

追記:SPCSではステージをマウントして使うことができるので処理したいファイルがあるステージをマウントすることで普通にファイルを扱うノリで変換処理ができます。(オブジェクトストレージ的な制約はあるけど今回は気にならない)

ci_push.pyとci_spcs.pyにまとめてあります。

レポジトリにイメージアップロード

$ uv run python ci_push.py   --repo SNOWFLAKE_LEARNING_DB.DATA_TEST.DOC_TOOLS   --image lo-convert --tag latest   --build   --put-spec --spec-path specs/lo_convert.yaml   --stage @SNOWFLAKE_LEARNING_DB.DATA_TEST.DOC_STAGE --spec-dest specs/lo_convert.yaml   --connection XVRALMC-UX32060
+ snow spcs image-registry login --connection XVRALMC-UX32060
Login Succeeded
+ snow spcs image-registry url --connection XVRALMC-UX32060
[INFO] registry host: xvralmc-ux32060.registry.snowflakecomputing.com
+ snow spcs image-repository create DOC_TOOLS --if-not-exists --connection XVRALMC-UX32060 --database SNOWFLAKE_LEARNING_DB --schema DATA_TEST
+-----------------------------------------------------------------+
| key    | value                                                  |
|--------+--------------------------------------------------------|
| status | DOC_TOOLS は既に存在し、ステートメントは成功しました。 |
+-----------------------------------------------------------------+
+ docker build -t lo-convert:latest -f Dockerfile .
[+] Building 1.5s (9/9) FINISHED                                  docker:default
 => [internal] load build definition from dockerfile                        0.0s
 => => transferring dockerfile: 953B                                        0.0s
 => [internal] load metadata for docker.io/library/debian:bookworm-slim     0.8s
 => [internal] load .dockerignore                                           0.0s
 => => transferring context: 2B                                             0.0s
 => [1/4] FROM docker.io/library/debian:bookworm-slim@sha256:7e490910eea28  0.0s
 => [internal] load build context                                           0.0s
 => => transferring context: 32B                                            0.0s
 => CACHED [2/4] RUN apt-get update &&     apt-get install -y --no-install  0.0s
 => CACHED [3/4] COPY convert.py /usr/local/bin/convert.py                  0.0s
 => CACHED [4/4] RUN chmod +x /usr/local/bin/convert.py && mkdir -p "/root  0.0s
 => exporting to image                                                      0.0s
 => => exporting layers                                                     0.0s
 => => writing image sha256:2a99acccb1fa3b7f0093aace5b5d58640cbf131f159ae6  0.0s
 => => naming to docker.io/library/lo-convert:latest                        0.0s
+ docker tag lo-convert:latest xvralmc-ux32060.registry.snowflakecomputing.com/snowflake_learning_db/data_test/doc_tools/lo-convert:latest
+ docker push xvralmc-ux32060.registry.snowflakecomputing.com/snowflake_learning_db/data_test/doc_tools/lo-convert:latest
The push refers to repository [xvralmc-ux32060.registry.snowflakecomputing.com/snowflake_learning_db/data_test/doc_tools/lo-convert]
6d1f23f8dbe2: Pushed 
b0069f1b9d95: Pushed 
e063546a29d4: Pushed 
aca836066730: Layer already exists 
latest: digest: sha256:f3f0fc82a70c5fd13206a9f917d8dca807d5dc859a9777417eaca7537e558504 size: 1158
[INFO] pushed: xvralmc-ux32060.registry.snowflakecomputing.com/snowflake_learning_db/data_test/doc_tools/lo-convert:latest
+ snow sql -q 'PUT file:///home/myu65/soffice/specs/lo_convert.yaml @SNOWFLAKE_LEARNING_DB.DATA_TEST.DOC_STAGE/specs/lo_convert.yaml AUTO_COMPRESS=FALSE OVERWRITE=TRUE;' --connection XVRALMC-UX32060
PUT file:///home/myu65/soffice/specs/lo_convert.yaml @SNOWFLAKE_LEARNING_DB.DATA_TEST.DOC_STAGE/specs/lo_convert.yaml AUTO_COMPRESS=FALSE OVERWRITE=TRUE;
+-------------------------------------------------------------------------------+
|         |         |         |         | source_ | target_ |         |         |
|         |         | source_ | target_ | compres | compres |         |         |
| source  | target  | size    | size    | sion    | sion    | status  | message |
|---------+---------+---------+---------+---------+---------+---------+---------|
| lo_conv | lo_conv | 758     | 758     | NONE    | NONE    | UPLOADE |         |
| ert.yam | ert.yam |         |         |         |         | D       |         |
| l       | l       |         |         |         |         |         |         |
+-------------------------------------------------------------------------------+

[INFO] spec PUT -> @SNOWFLAKE_LEARNING_DB.DATA_TEST.DOC_STAGE/specs/lo_convert.yaml
✅ 完了

実行

uv run python ci_spcs.py job   --pool LO_POOL_XS   --stage @DOC_STAGE   --spec specs/lo_convert.yaml   --database SNOWFLAKE_LEARNING_DB   --schema DATA_TEST    --connection XVRALMC-UX32060
+ snow sql -q 'USE DATABASE SNOWFLAKE_LEARNING_DB; USE SCHEMA DATA_TEST; PUT file:///tmp/tmp87gfnkie/lo_convert_DOC_JOB_20251004152457_20251004152457_d2f0912e.yaml @DOC_STAGE/specs AUTO_COMPRESS=FALSE OVERWRITE=TRUE;' --connection XVRALMC-UX32060
USE DATABASE SNOWFLAKE_LEARNING_DB;
+----------------------------------------+
| status                                 |
|----------------------------------------|
| ステートメントは正常に実行されました。 |
+----------------------------------------+

USE SCHEMA DATA_TEST;
+----------------------------------------+
| status                                 |
|----------------------------------------|
| ステートメントは正常に実行されました。 |
+----------------------------------------+

PUT file:///tmp/tmp87gfnkie/lo_convert_DOC_JOB_20251004152457_20251004152457_d2f0912e.yaml @DOC_STAGE/specs AUTO_COMPRESS=FALSE OVERWRITE=TRUE;
+------------------------------------------------------------------------------------------------------------------------+
|                 |                 |             |             | source_compress | target_compress |          |         |
| source          | target          | source_size | target_size | ion             | ion             | status   | message |
|-----------------+-----------------+-------------+-------------+-----------------+-----------------+----------+---------|
| lo_convert_DOC_ | lo_convert_DOC_ | 700         | 700         | NONE            | NONE            | UPLOADED |         |
| JOB_20251004152 | JOB_20251004152 |             |             |                 |                 |          |         |
| 457_20251004152 | 457_20251004152 |             |             |                 |                 |          |         |
| 457_d2f0912e.ya | 457_d2f0912e.ya |             |             |                 |                 |          |         |
| ml              | ml              |             |             |                 |                 |          |         |
+------------------------------------------------------------------------------------------------------------------------+

[INFO] spec PUT -> @DOC_STAGE/specs/lo_convert_DOC_JOB_20251004152457_20251004152457_d2f0912e.yaml
+ snow sql -q 'USE DATABASE SNOWFLAKE_LEARNING_DB; USE SCHEMA DATA_TEST; EXECUTE JOB SERVICE
          IN COMPUTE POOL LO_POOL_XS
          FROM @DOC_STAGE
          SPECIFICATION_FILE='"'"'specs/lo_convert_DOC_JOB_20251004152457_20251004152457_d2f0912e.yaml'"'"'
          NAME=DOC_JOB_20251004152457
          ASYNC=TRUE
          REPLICAS=1;' --connection XVRALMC-UX32060
USE DATABASE SNOWFLAKE_LEARNING_DB;
+----------------------------------------+
| status                                 |
|----------------------------------------|
| ステートメントは正常に実行されました。 |
+----------------------------------------+

USE SCHEMA DATA_TEST;
+----------------------------------------+
| status                                 |
|----------------------------------------|
| ステートメントは正常に実行されました。 |
+----------------------------------------+

EXECUTE JOB SERVICE
          IN COMPUTE POOL LO_POOL_XS
          FROM @DOC_STAGE
          SPECIFICATION_FILE='specs/lo_convert_DOC_JOB_20251004152457_20251004152457_d2f0912e.yaml'
          NAME=DOC_JOB_20251004152457
          ASYNC=TRUE
          REPLICAS=1;
+-------------------------------------------------------------------+
| status                                                            |
|-------------------------------------------------------------------|
| Started Snowpark Container Services Job 'DOC_JOB_20251004152457'. |
+-------------------------------------------------------------------+

[INFO] job name: DOC_JOB_20251004152457

ってな感じで実行できます。

結果

$ docker run --rm -v "$PWD/in:/in" -v "$PWD/out:/out" lo-convert   python3 /usr/local/bin/convert.py --passthrough-modern --calc-fit-export    --inputs "/in/**/*"     --out-dir "/out" --also-pdf

これで…

image.png

こうじゃ。
image.png

xlsファイルがpdfになっています。ちなみにこのページはデフォルトだと横にはみ出て2ページにわかれてました。

Snowflakeでも、

これが、
image.png

こうじゃ
image.png

で、で、

よめなかったExcelも

SELECT 
  AI_PARSE_DOCUMENT(
    TO_FILE('@DOC_STAGE', 'raw/(様式)研究費とその必要性等.xlsx'),
    {'mode': 'LAYOUT'}
  );
{
  "errorInformation": "The provided file format .xlsx isn't supported. Supported formats: ['.docx', '.pptx', '.txt', '.html', '.png', '.jpg', '.tiff', '.jpeg', '.tif', '.pdf']."
}

PDFに変換されてるので

SELECT 
  AI_PARSE_DOCUMENT(
    TO_FILE('@DOC_STAGE', 'convert/out/(様式)研究費とその必要性等.pdf')
    ,{'mode': 'LAYOUT'}
  );

ばっちりMarkdownになっています
image.png

当然ほかのdocやpptもdocxやpptx、pdfになってるのでばっちりです。

やったね。

あ、おそらく真の神エクセルにはまだ試してないので、手も足もでない可能性はあります。探すとでてこないのでいい神エクセルあったら試してもらってもいいし押してくれたら28日いないなら試します(Snowflakeのトライアルアカウントの残日数)

21
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?