見出し画像

LibreOffice から Python Script for MacOSX 備忘録

概要

LibreOffice Calc Basic ではできないことが出てきて、Python の可能性を調査した。この記事はそんな過程の備忘録である。

No 忘備録
Yes 備忘録

どうでもいいけど。

最近、自然観察の記録を記事にし始めた。それの効率化を目指したところから話は始まる。

シートに、写真を貼り付ける。もちろんファイル名も自動で読み込む。

緯度経度を写真から読み取って Google Map で番地を確認。写真を見ながら、キャプションを記入する。この辺は手作業になる。

緯度経度が結構手間だったので、自動化したかった。LibreOffice(これ以降、LO と表記)Calc Basic では写真にエンベッドされた Exif データから GPS の情報を読み出すことはできない。というか、できないだろう。いろいろやってみた結果、俺にはできなかった。

で、Python Script を使ったらどうかということで検討した。そうしたら、LO から使える Python が専用のものだったので、モジュールを追加するところで行き詰ってしまった。

モジュールを追加して使うことは無理という結論。

そこで、昔、VBA をやっていたときに、VBA でできないところを Python Script で処理したことがあったので、それと同じようにやれば良いだろうということになった。

LO から Python

読んだけど、何を言っているのかわからない。

そこで検索。

↓こちらの書き込みからヒントを得た。

ま、主にサンプルスクリプトをもらっただけだ。

次に、前のサイトに戻って、もう一度読んでみる。

「マクロ/Pythonガイド/はじめに」の「マクロはどこに保存されますか?」

OSX の場合、

~/Library/Application Support/LibreOffice/4/user/Scripts/python/

Shift + Command + . で隠しフォルダーを表示する。

ユーザ>自分のフォルダー>ライブラリ>Application Supprt ....

で、python フォルダーに *.py というテキストファイルを保存すれば良い。

ドキュメントに保存したい。

ドキュメント内
Any ODF file, really is a ZIP file, you can extract this file like extract normally this type files. In the root, create folder
Scripts/python/
and copy inside any python file, for example:
mymacros.py


任意のODFファイルは、実際にはZIPファイルです、あなたはこのファイルを抽出することができます抽出のように通常このタイプのファイルを抽出します。ルートでは、フォルダを作成します。

ODF ファイルを展開して、Scripts/python/ というフォルダーを作ってそこにおけば良いとのこと。

で?どうやって展開するの?

App Store で The Unarchiver なるものをゲット。

インストールしたが、使い方がわからない。アイコンにドロップすれば良いのか。

The Unarchiver は、Application フォルダーにあった。ODF ファイルをドロップ。

開いた。

画像1

画像2


The Unarchiver は圧縮できないので、圧縮用に ZIPANG なるものをゲット。

フォルダーを作って Python Script を置き、また、指示に従って META-INF フォルダーの中の、manifest.xml に行を追加した。

Python Script のファイル名 "mymacros.py" は、自分が用意した名称に直した。

注意:フォルダーごとやったらダメ。解凍したルート以下の複数のフォルダーやファイルを ZIPANG のウィンドウにドロップ。

ファイル名を気にせずやったら、Configuration2.zip が書類フォルダーに保存された。

ファイル名を、*.odf に直して、開く。

マクロを確認すると、ちゃんとあった。

LibreOffice からは、編集できない。実行することしかできないようだ。

面倒だ。

Mac 用の Python

LO の Python の特殊性を理解していなかったので、わからないままに、Mac 用の Python 3.x.x をインストールした。

macOS users
For Python 3.8, we provide one installer: 64-bit-only that works on macOS 10.9 (Mavericks) and later systems.
Please read the "Important Information" displayed during installation for information about SSL/TLS certificate validation and the running the "Install Certificates.command".
Python 3.8については、macOS 10.9 (Mavericks)以降のシステムで動作する64ビット版のみのインストーラを提供しています。
SSL/TLS証明書の検証や「Install Certificates.command」の実行については、インストール時に表示される「重要なお知らせ」をお読みください。

DL

インストール

成功

モジュールってどうするの?

ま、いっか。

IDLE 起動。成功。

で、スクリプト、どうするの?

とか言って、一応、入門書は読破したのだが。珍しく全部読んだ。著者も良かったが、翻訳も良かった。

Mac の場合、なんか勝手が違うと感じるなあ。


ちょっと試しにファイル一覧をゲットしてみる。

>>> import glob
>>> files = glob.glob("/Users/-------/note/20200722_自然観察/*.jpg")
>>> for file in files:
	  print(file)

できるじゃん。Python 3.8.5 のインストーラーをもらってきて、インストールしたら、Application フォルダーに IDLE という名のアプリケーションが置かれて、それを起動したら、スクリプトを書くことができた。

俺の理解したところでは、Python の実行ファイルは見えないところにあって Mac のフィンダーからは見えないけれど、Python Launcher というアプリケーションが、ファインダーから実行したスクリプトを Python のアプリケーションに渡してくれるみたいだ。

ということは、モジュールは、ターミナルからコマンド打ち込んでやれば良いってことか。必要になったら、調べてやってみるとするか。

で、今必要なのは、EXIF 情報を読み出すモジュールだ。モジュールがなかったら EXIF を解釈するしかないか。バイナリー読んで解析。

できるのか、素人に。

これこれ。モジュールあった。

PIL というモジュールが必要なのか。


まずは、pip をインストールしないとはじまらない。

ターミナルを起動。

いきなり、sudo easy_install pip、エンター。

WARNING の後、パスワードを聞いてきた。

パスワードが入ったかどうかわからない表示。で、パスワードを入れた。エンター。

結果、pip 6.1.1 が入ったようだ。

Python 2.7 かよお。ん?pip3も入ったから良いのかな?

ま、このまま次に進むとするか。

pip install PIL ?

PIL 開発が止まっているのか。

Pillow を入れるとする。

sudo pip3 install Pillow、エンター。

Pillow 7.2.0 が入った。

LO から Python Script 編集

APSO 拡張機能
Alternative Python Script Organizer (APSO) 拡張機能は、特にドキュメントに埋め込まれている場合に、Python スクリプトの編集を容易にします。APSOを使うと、お好みのソースコードエディタを設定したり、統合されたPythonシェルを起動したり、Pythonスクリプトをデバッグしたりすることができます。任意のUNOオブジェクトを検査するための拡張機能が存在します。そのような拡張機能の詳細についてはDesigning & Developing Python Applicationsを参照してください。

どういうこと?


エディターとして、PyCharm ゲット。

あとは、Python Script でゲットした GPS 情報をどうやってセルに書き込むか、だ。

将来的には、地番杭の位置情報と照らし合わせて、それらしい地番をセルに書き込むところまでやれたらいいなと思う。

※ 地番杭=地名に相当


まず、「ツール」-「拡張機能マネージャ」を選択します。

Tools > Extension Manager...

「ほかの拡張機能をオンラインで取得」を選択します。

Get more extensions online...

Python で検索。

APSO - Alternative Script Organizer for Python 出た。

クリック。

説明はあと。

はい、迷子になりました。

Release List の一番上の右端の EXTERNAL LINK という緑色のボタン?

ダウンロードした。

APSO.oxt

LibreOffice に戻る。Extension Manager の Add ボタンをクリック。

ダウンロードフォルダーにあるので選択する。

Extension Software License Agreement ウィンドウ、出た。Accept をクリック。

ライセンスアグリーメントを全部読めと。

Accept ボタンをクリックする。結果、ライセンスに合意したことになる。

右の Scroll Down ボタンはライセンス条項をスクロールするためのものだった。手順がスクロールするのかと思った。レイアウトに問題がある。

ま、いいさ。

Adding APSO.oxt とか出て、すぐに消える。

::APSO:: 1.2.6.2 が追加された。

Close をクリック。

For the extension to work properly, LibreOffice must be restarted. 

Do you want to restart LibreOffice now?

と聞くので、Restart Now をクリック。

初期画面になる。

ファイルを開く。

さてと、


LibreOffice CalcでPythonマクロを使う(3)

Tools > Macros > Organize python scripts と選択。

このファイルを選択して、Menu をクリック。

Create module
Create library
---------------------------
Python shell

と出た。

Create module を選択。モジュール名に、my_first_macro_calc と入力。次へ。

モジュールを選んだときは、違う Menu が表示される。


Edit
Substitute
Rename
-------------------------
Export
Delete
--------------------------
Python shell


Edit を選択。

何も変化なし。

 PyCharm を設定するか。

念のため、PyCharm を起動してみる。

JetBrains Privacy Policy が表示された。次へ。

DATA SHARING 画面。次へ。

You can always change this behavior in Preferences | Appearance & Behavior | System Settings | Data Sharing.

Customize PyCharm ウィンドウ。

I've never used PyCharm。 ま、このままにして次へ。

UI theme の設定。黒バックか白バックか、ということか。白バックに。

Create Launcher Script 、設定なしで次へ。

Download featured plugins 

IdeaVim, R, AWS Toolkit の3つが表示されている。Install しない。

最後のボタンだ。Start using PyCharm をクリックする。

Welcome to PyCharm ダイアログ。

+ Create New Project

フォルダーアイコンに Open

左下向き矢印と Get from Version Control

右下には、歯車アイコンに Configure、Get Help の2項目が見える。

Create New Project を選択。

画像3

なんのことやら。

ま、このまま Create してみるとする。

Creating Virtual Environment が表示され、次に、Tip of the Day ウィンドウ。

うーん、どうすれば良い?

LibreOffice から PyCharm を起動するのか。


APSO Options
The extension option page is available under Tools -> Extension Manager -> APSO -> Options.

Extension Maneger のリストから ::APSO:: を選択して、左下 option をクリック。

Options - apso - EditorKicker ウィンドウ。

Editor を設定するところ、Choose クリック。アプリケーションから PyCharm を選択。

Content of new module に

# coding: utf-8
from __future__ import unicode_literals

素人はいじらず、OK をクリックするのであった。

で、結果、何も起きず。

考えられることは、MacOSX の場合、アプリケーション(*.app)を選択しても、それがフルパスじゃあないってこと。

PyCharm のアイコンを右クリック、パッケージの内容を表示する。

Contents/MacOS/pycharm これが本体らしい。

こいつのフルパスを手入力したら、起動できた。

開いたウィンドウに、サンプルコードをペースト。

さて、次はどうしたら良いのだろうか。



APSO にデバッガーがあるようなので、あとで役に立つかもしれないので、読んでおくか。


The debugger can be launched from the Apso Menu button when a function is selected in the main window.
Once the debuuger opened, one can execute the code step by step, enter any called function, return to the caller, etc.
Break points are not supported, but you can jump ahead by double clicking any line below the current one within the same function.
You can check any caller state and scope by double clicking it in the "Stack" window (bottom left). If you have MRI or Xray installed, you can inspect any UNO variables by double clicking it in the "Scope" window (bottom right).
When you open a console window from the tool bar, the global and local scope will be automatically loaded.
If you edit the script while the debugger is running, changes will be taken in account after clicking "Restart".
The debugger uses the font name and height defined for the Basic IDE.


メインウィンドウにおいてある関数を選択すると、Apsoメニューボタンからデバッガーを起動できます。
デバッガを開くと、ステップバイステップでコードを実行したり、呼び出された関数を入力したり、呼び出し元に戻ったりすることができます。
ブレークポイントはサポートされていませんが、同じ関数内で現在の行より下の行をダブルクリックすることで先にジャンプすることができます。
呼び出し元の状態やスコープは、"Stack "ウィンドウ(左下)でダブルクリックすることで確認できます。MRIやXrayがインストールされている場合は、"Scope "ウィンドウ(右下)でダブルクリックすることでUNO変数を検査することができます。
ツールバーからコンソールウィンドウを開くと、グローバルスコープとローカルスコープが自動的に読み込まれます。
デバッガの実行中にスクリプトを編集した場合、「Restart」をクリックした後に変更が考慮されます。
デバッガは、Basic IDE で定義されたフォント名と高さを使用します。

www.DeepL.com/Translator(無料版)で翻訳しました。

LibreOffice のファイルに Python Script を保存する話だった。

とりあえず、サンプルが動作するか、するだろうけど。

ODF ファイルを解凍、新しく作ったスクリプトを上書きして、圧縮。拡張子を、zip から odf に変えて実行。できた。

 

マクロ実行。エラー発生。おやおや。

スクリプトをみたら、

import numpy とあった。パクっただけで、中身を読んでいなかった。

numpy を導入。

なんで bumpy に直すか、余計なことをするやつだな。

※ MacOS が勝手にスペルミスを修正していた。

ターミナルから、sudo pip3 install numpy、エンター。

パスワードを聞いてくる。この Mac 用のパスワードを入れて、エンター。

無事にインストール完了。

ダメか。まあ、だめだと思ったさ。

このスクリプトを選んで、Dbugger を起動。手順を確認するために、Debugger Quit。

デバッガーウィンドウが閉じた。

おやおや?スプレッドシートだけになった。何もできない。

時間が経ったら戻った。タイムアウトしたのだろうか。

Tools > Macros > Organize python scripts

このスクリプトを選択して、Menu。

MacOS の日本語環境設定で、入力中のスペルチェックを停止。

Menu が
Edit
----------------------------
Delete
----------------------------
Debug
Python shell

Debug を選択。

コピペのときに、2行忘れてた。2行追加して、再び。しかし、エラー。

A Scripting Framework error occurred while running the Python script vnd.sun.star.script:my_first_macro_calc.py$my_first_macro_calc?language=Python&location=document.
Message: <class 'ModuleNotFoundError'>: No module named 'numpy'
File "/Applications/LibreOffice.app/Contents/Resources/pythonscript.py", line 1063, in getScript
mod = self.provCtx.getModuleByUrl( fileUri )
File "/Applications/LibreOffice.app/Contents/Resources/pythonscript.py", line 500, in getModuleByUrl
exec(code, entry.module.__dict__)
File "vnd.sun.star.tdoc:/3/Scripts/python/my_first_macro_calc.py", line 4, in <module>
File "/Applications/LibreOffice.app/Contents/Resources/uno.py", line 356, in _uno_import
return _builtin_import(name, *optargs, **kwargs)

エラーメッセージを再確認。

numpy というモジュールはないってさ。

Python shell で import numpy と打ったらエラーは出ない。

import uno と打ったらエラーが出た。

うーん。これは。ありがち。

しかし、素人には解決できない問題だな。

sudo apt-get install libreoffice-script-provider-python、エンター

apt-get というコマンドはないと言う。

いろいろ調べると、apt-get はもう古くて、apt だとか話している。

で、apt を試す。

sudo apt install libreoffice-script-provider-python

今度は次のエラー。

Unable to locate an executable at "/Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home/bin/apt" (-1)


LibreOffice の Python は LibreOffice 用であって、俺がインストールした Python 3.8.5 ではない。

前者は LibreOffice で使えるが、後者は使えない。

LibreOffice から起動するスクリプトは、あとから追加したモジュールを使えない。

ま、何かやり方があるのだろうけれど、現時点では情報を持っていない。


この際、Python から LibreOffice を操作する方向に切り替えた方が良いのではないかと思う。

LibreOffice の Python のバージョンを確認。Python の実行ファイルをダブルクリックしたら、開いたウィンドウに表示された。

Python 3.7.7



この最初の回答にLibreOfficeのバンドルPythonにPythonパッケージを追加する方法のQ&Aが書いてあります。



Hi everybody,

I am using Windows 8.1 and LibreOffice 4.4.2.2. Scripting with the standard library of Python seems to work quite well, but I am having a hard time making the package "requests" work. Since I couldn't find pip or anything like that I downloaded the source directory into C:\Program Files (x86)\LibreOffice 4\program\ and executed within the source directory "C:\Program Files (x86)\LibreOffice 4\program\python.exe setup.py install", which seemed to work at the first glance, but when I try to run the following script:


皆さんこんにちは。

私はWindows 8.1とLibreOffice 4.4.2.2を使用しています。Pythonの標準ライブラリを使ったスクリプトはうまくいくようですが、パッケージの「リクエスト」がうまくいかなくて困っています。pipとかが見つからないので、ソースディレクトリをC:\Program Files (x86)\LibreOffice 4\\programにダウンロードして、ソースディレクトリ内の "C:\Program Files (x86)\LibreOffice 4\program\python.exe setup.py install "を実行すると、一見うまくいくように見えたのですが、以下のスクリプトを実行しようとすると。


import ctypes, requests
def blabla(*args):
   yahoo_url="http://download.finance.yahoo.com/d/quotes.csv?s=" + "+ABX+ALV.DE" +"&f=l1t1d1xphgkjva2m3m4on&e=.csv"
   r = requests.get(yahoo_url)
   ctypes.windll.user32.MessageBoxW(0, r.text, "Yahoo says:", 1)`
I get the following error message:


Ein Scripting Framework Fehler trat während der Ausführung vom Python-Skript vnd.sun.star.script:PyOffice|coco.py$blabla?language=Python&location=share auf.
Meldung: <class 'importerror'="">: cannot import name utils
 C:\Program Files (x86)\LibreOffice 4\program\python-core-3.3.3\lib\site-packages\requests\__init__.py:58 in function <module>() [from . import utils]
 C:\Program Files (x86)\LibreOffice 4\program\uno.py:265 in function _uno_import() [return _g_delegatee( name, *optargs, **kwargs )]
 C:\Program Files (x86)\LibreOffice 4\share\Scripts\python\PyOffice\coco.py:1 in function <module>() [import ctypes, requests]
 C:\Program Files (x86)\LibreOffice 4\program\pythonscript.py:451 in function getModuleByUrl() [exec(code, entry.module.__dict__)]
 C:\Program Files (x86)\LibreOffice 4\program\pythonscript.py:992 in function getScript() [mod = self.provCtx.getModuleByUrl( fileUri )]


Thx in advance for any help!

回答


try to edit C:\Program Files (x86)\LibreOffice 4\program\python-core-3.3.3\lib\site-packages\requests\__init__.py
change Lines 58 to 63 to:
from requests import utils
from requests.models import Request, Response, PreparedRequest
from requests.api import request, get, head, post, patch, put, delete, options
from requests.sessions import session, Session
from requests.status_codes import codes
from requests.exceptions import (


If you have a copy of the same major and minor version of Python installed on your system (Python 3.3.x for LO 4.3 and 4.4 current releases) then you essentially have two possible solutions to reach the same goal. If, however, you do not have the same Python branch installed then only one option is reliably available to you.
That solution is to install pip (and setuptools) within the LibreOffice installation and then use the pip program (script) to install anything else. Likewise, calling the full path to the LO version of Python when installing with a setup.py file will do much the same thing.
The alternative method, if you have a regular installation of Python 3.3 or are willing to try it with 3.4 (which might be bad and might break other things, so be careful) then all you need to do is make sure that the LibreOffice Python can access the site-packages directories which exist elsewhere on the system.
Run this script with the system version of Python 3.3:
もしあなたのシステムに同じメジャーバージョンとマイナーバージョンの Python のコピーがインストールされている場合 (LO 4.3 と 4.4 の現行リリースでは Python 3.3.x)、本質的には同じゴールに到達するために 2 つの可能性のある解決策があります。しかし、同じ Python ブランチがインストールされていない場合は、1 つのオプションしか確実に利用できません。
それは、LibreOffice の中に pip (と setuptools) をインストールし、それ以外のものは pip プログラム (スクリプト) を使ってインストールすることです。同様に、setup.py ファイルを使ってインストールする際に、Python の LO バージョンへのフルパスを呼び出しても、ほとんど同じことができます。
別の方法としては、Python 3.3を定期的にインストールしている場合や、3.4で試してみたいと思っている場合(これはまずいかもしれませんし、他のものを壊すかもしれないので注意が必要です)は、LibreOffice Pythonがシステム上の他の場所にあるsite-packagesディレクトリにアクセスできることを確認するだけでよいでしょう。
このスクリプトをシステムバージョンのPython 3.3で実行してください。
www.DeepL.com/Translator(無料版)で翻訳しました。
import sys
afile = open("sites.pth", "w")
for s in sys.path:
   afile.write(s+"\n")
afile.close()
Then copy or move the sites.pth file it creates to a LibreOffice directory which should include something like this: LibreOfficePython.framework/Versions/3.3/lib/python3.3/site-packages/
Note: I'm checking an OS X system here, so there will be path differences, but basically you want to find the site-packages directory for the LO installation and copy the sites.pth file there. That file will be checked by Python for additional locations to check for modules and thus will find the modules installed for your regular Python installation, including requests if it's there.
Oh, by the way, on an unrelated note, there are better options than ctypes, depending on what you're doing. Take a look at Cython and CFFI, more likely CFFI.
次に、作成した sites.pth ファイルを LibreOffice ディレクトリにコピーまたは移動します。LibreOfficePython.framework/Versions/3.3.3/lib/python3.3/site-packages/
注意: ここでは OS X システムをチェックしているのでパスの違いはあるでしょうが、基本的には LO インストール用の site-packages ディレクトリを見つけ、そこに sites.pth ファイルをコピーします。そのファイルはPythonによってモジュールをチェックする場所が追加されているかどうかチェックされるので、そこにあればリクエストも含めて通常のPythonインストール用にインストールされているモジュールを見つけることができます。
あ、ところで、関係ない話ですが、あなたが何をしているかによっては、ctypesよりも良いオプションがあります。CythonとCFFI、どちらかというとCFFIを見てみましょう。
www.DeepL.com/Translator(無料版)で翻訳しました。


site-packages ディレクトリーを探せ。

/Users/ユーザー名/PycharmProjects/untitled/venv/lib/python3.8

PyCharm 用のやつか。

なかったら作るのか?


結果、Python Script を実行するときには、LibreOffice の Python とは別の Python が起動して、あとから入れたモジュールが使えるが、uno は使えない、つまり LibreOffice と関連したプログラムができない。

一方、LibreOffice から Python Script を使う場合には、uno は動くが、あとからインストールしたモジュールが使えない。


IDLE を起動。表示から、Python 3.8.5 で動いていることがわかる。

ターミナルから python --version と入れて確認すると、

Python 2.7.10 と出る。

上のサイトを参考にして、IDLE から対話形式でスクリプトを実行。

>>> import sys
>>> import pprint
>>> pprint.pprint(sys.path)

/Users/ユーザー名/Documents とあるのは、MacOS 上のパス。

ならば、

LibreOffice の uno.py へのパスも同様に記述したらうまく行くのではないだろうか。

→ Mac の Python から LibreOffice をなんとかできないかと考えている。

おそらく MacOS 上の Path ではないな。

/Applications/LibreOffice.app/Contents/Resources/uno.py

問題を解決するには、

LibreOffice 用の Python が追加のモジュールを使えるようにする。

または、

Python 用に LibreOffice 用の uno.py への Path を通す。

どちらもやり方がわからない。いや、後の方は多分やればできる。

いろいろ調べると、LibreOffice  は自分用の Python をインストールしていた。LibreOffice 用のPython は、LibreOffice.app パッケージを開くと中にある。

Windows の場合、Windows の領域に、Python 一式も存在するので、LO に対して PATH 云々が可能かもしれない。

Mac の場合、LO の アプリケーションパッケージの中に Python の実行ファイルが置かれているが、Python 周りの構成が普通じゃないというか、理解できない。


で、あきらめた。

LO 用に Python モジュールをインストールすることはできない
LO 用の Python を別途インストールした Python に置き換えることもできない
Python に uno なんちゃらをインストールできたとしても違う領域にある Mac 用の LO をどうこうすることはできない。

それが俺の結論。

とりあえずのやり方でやっておくことにする。

無理と分かったので次善の策だ。

Python と LO で業務を分担するのだ。

Mac にインストールした Python を使って、GPS 情報を csv ファイルにする。LO の外で下処理するのだ。

LO Basic では 画像一覧を作成し、次に Python Script で作った csv ファイルの情報を読み込む。

園内の番地情報も csv ファイルにしてあって、その緯度経度から撮影地点までの距離の計算までできている。

Google Map は、GPS の即位が間違っていないかどうかを確認するためだけに使っている。

試行錯誤してやっと jpeg ファイルから GPS データを読みだして、最も近い地番杭と紐付けることができた。

どこまで書けるかわからないが、具体的な話は近いうちに記事にまとめようと思う。

t.koba




この記事が気に入ったらサポートをしてみませんか?