2020年11月15日日曜日

49: LibreOffice/OpenOfficeにドキュメント内Pythonマクロを作成する

<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>

GUIを見る限りできないように見えますが、実際にはできます。したがって、マクロをドキュメント内に置くためのだけにBasicを使用する必要はありません。

話題


About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: Pythonプログラミング言語

この記事の目次


開始コンテキスト


  • 読者は、LibreOfficeまたはApache OpenOfficeの基本的知識を持っている。
  • 読者は、Pythonプログラミング言語の基本的知識を持っている。

ターゲットコンテキスト



  • 読者は、LibreOfficeまたはOpenOfficeで、ドキュメント内Pythonマクロを作成する方法を知る。

オリエンテーション


ユーザー所有またはアプリケーション所有のPythonマクロを作成することは、前記事にて取り扱われました。

任意のマクロ(ユーザー所有、アプリケーション所有、ドキュメント内)ファンクションをあなたのUNOプログラムから実行することは、ある以降の記事にて取り扱われます。

Pythonマクロプログラミングの詳細は、いくつかの以降の記事群にて探求されます。

外部フルPythonを使用することは、以前のある記事にて取り扱われました。

ト書き
Hypothesizer 7、Objector 49A、Objector 49Bが、コンピューターの前にいる。


本体


1: Pythonマクロは、任意の'odt'、'ods'、'odp'、'odb'、'odf'、'odg'ファイル内に置くことができる


Hypothesizer 7
Pythonマクロは、任意の'odt'、'ods'、'odp'、'odb'、'odf'、'odg'ファイル内に置くことができます。

Objector 49A
マジじゃないよな?

Hypothesizer 7
私はとても真剣です、サー。

Objector 49A
でも、できないと聞いたが。

Hypothesizer 7
それでは、そう言われた方は、方法をご存知なかったのでしょう。

Objector 49A
みんなそう言ったんだ!

ト書き
Hypothesizer 7は、悲しげに首を振る。

Hypothesizer 7
私は言いませんでした、サー. . .

Objector 49A
だが、GUIはさせてくれないぞ。

Hypothesizer 7
えーと、何ができるかをGUIは示しているという誤解が広くあるようです。実際には、GUIが示しているのは、GUIを介して何ができるかだけです。

Objector 49A
. . .そのGUIを見れば、ドキュメント内Pythonは許されないとみんな思うだろう!

ト書き
Hypothesizer 7は、悲しげに首を振る。

Hypothesizer 7
私は思いません、サー。あのう、「みんな」という言葉は、不用意に使用されるべきではありません

Objector 49B
それじゃあ、マクロをドキュメント内にいれるには、何かコマンドを1つ実行しろというのね?

Hypothesizer 7
マダム、実際には、1つのコマンドでは済みません。

Objector 49B
難しそうじゃない!

Hypothesizer 7
マクロを作成しようと試みられる方であれば、どなたでも問題なくできるはずです、私の意見では。

Objector 49A
「どなたでも」を不用意に使うべきじゃない!

Hypothesizer 7
私はそれを注意深く使用しました、サー。私は文字通りそれを意味しています: あなたは学ぶべきです、もしも、本当に現在できないのであれば。


2: Pythonマクロを、任意の'odt'、'ods'、'odp'、'odb'、'odf'、'odg'ファイル内に置く方法


Hypothesizer 7
'odt'、'ods'、'odp'、'odb'、'odf'、'odg'ファイルはどれも、本当は、ZIPファイルです。

Objector 49B
そうなの?ファイルは普通に展開できるの?

Hypothesizer 7
はい、おできになります。

例えば、この'MacroTests.odt'という'odt'ファイルを'fileIngredients'というディレクトリ内に展開してみましょう、以下のように、このLinuxマシンで。

@bash ソースコード
l_targetFileName="MacroTests.odt"; l_expansionDirectoryName="fileIngredients"; mkdir "./${l_expansionDirectoryName}"; cp "./${l_targetFileName}" "./${l_expansionDirectoryName}/."; cd "./${l_expansionDirectoryName}"; unzip "./${l_targetFileName}"; rm "./${l_targetFileName}"

Objector 49B
. . .えーと、私はLinuxを使わないんだけど、ファイルは、どんな方法でも、とにかく展開すればいいんでしょう?

Hypothesizer 7
そうです、マダム。

次に、当該Pythonマクロファイルを、その展開ディレクトリ内の'Scripts/python'ディレクトリ(ご自分で作成される必要があります)配下にコピーします、以下のように('PythonEnvironmentChecker.py'は、当該Pythonマクロファイルです)。

@bash ソースコード
l_macroBasePath=~/"myData/development/pythonEnvironmentCheckerUnoExtension/source/python"; l_macroPackagePath="theBiasPlanet/pythonEnvironmentChecker/macros"; l_macroFileName="PythonEnvironmentChecker.py"; mkdir -p "./Scripts/python/${l_macroPackagePath}"; cp "${l_macroBasePath}/${l_macroPackagePath}/${l_macroFileName}" "./Scripts/python/${l_macroPackagePath}/."

Objector 49B
「theBiasPlanet/pythonEnvironmentChecker/macros」?

Hypothesizer 7
それは、Pythonモジュールを任意のパッケージ内に置くことができることをデモンストレーションするためです。勿論、Pythonモジュールファイルを直接'Scripts/python'内に置くこともできます、そうお望みならば。

Objector 49B
ふーん。

Hypothesizer 7
次に、'META-INF/manifest.xml'ファイルを編集して、以下を'manifest:manifest'ノード内の既存子ノード群の後に追加します。

@xml ソースコード
 <manifest:file-entry manifest:full-path="Scripts" manifest:media-type="application/binary">
 </manifest:file-entry>
 <manifest:file-entry manifest:full-path="Scripts/python" manifest:media-type="application/binary">
 </manifest:file-entry>
 <manifest:file-entry manifest:full-path="Scripts/python/theBiasPlanet" manifest:media-type="application/binary">
 </manifest:file-entry>
 <manifest:file-entry manifest:full-path="Scripts/python/theBiasPlanet/pythonEnvironmentChecker" manifest:media-type="application/binary">
 </manifest:file-entry>
 <manifest:file-entry manifest:full-path="Scripts/python/theBiasPlanet/pythonEnvironmentChecker/macros" manifest:media-type="application/binary">
 </manifest:file-entry>
 <manifest:file-entry manifest:full-path="Scripts/python/theBiasPlanet/pythonEnvironmentChecker/macros/PythonEnvironmentChecker.py" manifest:media-type="">
 </manifest:file-entry>

Objector 49B
面倒ねえ. . .

Hypothesizer 7
でも、おできになれるでしょう?

Objector 49B
できないとは言わないけどねえ、面倒よ。

Hypothesizer 7
最終ステップは、展開ディレクトリを再アーカイブすることです、以下のように。

@bash ソースコード
zip -r "../${l_targetFileName}" *

Objector 49B
面倒なステップ群ね。

Hypothesizer 7
そうではなく、以下のような1つのシェルスクリプトまたはバッチファイルを実行なさればよいだけです、それでも、マニフェストファイルは編集なさる必要がありますが。

@bash ソースコード
#!/bin/bash
# supposed to be executed at the target file directory

l_targetFileName="$1"
l_modeName="$2" # 'add' or 'remove'
l_macroBasePath="$3" # empty if the mode name is 'remove'
l_macroPackagePath="$4" # can be empty if the mode name is 'remove' (the 'Scripts' path will be removed)
l_macroFileName="$5" # can be empty if the mode name is 'remove'
l_expansionDirectoryName="fileIngredients"

set -x

cp "./${l_targetFileName}" "./${l_targetFileName}.save"
mkdir "./${l_expansionDirectoryName}"
mv "./${l_targetFileName}" "./${l_expansionDirectoryName}/."
cd "./${l_expansionDirectoryName}"
unzip "./${l_targetFileName}"
rm "./${l_targetFileName}"
if [ "${l_modeName}" == "add" ]; then
        if [ ! -d "./Scripts/python/${l_macroPackagePath}" ]; then
                mkdir -p "./Scripts/python/${l_macroPackagePath}"
        fi
        cp "${l_macroBasePath}/${l_macroPackagePath}/${l_macroFileName}" "./Scripts/python/${l_macroPackagePath}/."
else
        if [ "${l_macroPackagePath}" != "" ]; then
                rm -r "./Scripts/python/${l_macroPackagePath}/${l_macroFileName}"
        else
                rm -r "./Scripts"
        fi
fi
vim "META-INF/manifest.xml"
zip -r "../${l_targetFileName}" *
cd ..
rm -r "./${l_expansionDirectoryName}"

Objector 49B
その編集部分が面倒なわけ。

Hypothesizer 7
その編集を行なうPythonプログラムを作成することができます、以下のように。

theBiasPlanet/inDocumentPythonMacrosRegistrar/programs/InDocumentPythonMacrosRegistrarConsoleProgram.py

@Python ソースコード
from typing import List
from typing import Optional
from typing import TextIO
from typing import cast
from collections import OrderedDict
import os
from pathlib import Path
import shutil
import sys
import xml.sax
import xml.sax.handler
from xml.sax.handler import ContentHandler
from xml.sax.xmlreader import AttributesImpl
from xml.sax.xmlreader import XMLReader
from theBiasPlanet.coreUtilities.constantsGroups.DefaultValuesConstantsGroup import DefaultValuesConstantsGroup
from theBiasPlanet.coreUtilities.constantsGroups.FileNameSuffixesConstantsGroup import FileNameSuffixesConstantsGroup
from theBiasPlanet.coreUtilities.constantsGroups.FileOpenModeNamesConstantsGroup import FileOpenModeNamesConstantsGroup
from theBiasPlanet.coreUtilities.constantsGroups.GeneralConstantsConstantsGroup import GeneralConstantsConstantsGroup
from theBiasPlanet.coreUtilities.constantsGroups.XmlExpressionsConstantsGroup import XmlExpressionsConstantsGroup
from theBiasPlanet.coreUtilities.messagingHandling.Publisher import Publisher
from theBiasPlanet.coreUtilities.xmlDataHandling.XmlDatumHandler import XmlDatumHandler

"""
mode name: "add" or "remove"
"""
class InDocumentPythonMacrosRegistrarConsoleProgram:
	c_manifestFileRelativePath: Path = Path ("META-INF/manifest.xml")
	c_scriptsBaseDirectoryRelativePath: Path = Path ("Scripts")
	c_pythonBaseDirectoryRelativePath: Path = c_scriptsBaseDirectoryRelativePath.joinpath ("python")
	c_addModeName = "add"
	c_removeModeName = "remove"
	class ManifestDatumParseEventsHandler (ContentHandler):
		c_rootElementName: str = "manifest:manifest"
		c_filePathElementName: str = "manifest:file-entry"
		c_pathAttributeName: str = "manifest:full-path"
		c_mediaTypeAttributeName: str = "manifest:media-type"
		c_binaryMediaTypeName = "application/binary"
		c_emptyMediaTypeName = GeneralConstantsConstantsGroup.c_emptyString
		c_pythonModuleFileGlobExpression = GeneralConstantsConstantsGroup.c_fileNameFormat.format (GeneralConstantsConstantsGroup.c_doubleAsterisks, FileNameSuffixesConstantsGroup.c_pythonModuleFileNameSuffix)
		
		def __init__ (a_this: "InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler", a_modeName: str, a_concernedPathToIsFoundMap: "OrderedDict [Path, bool]", a_writer: TextIO) -> None:
			a_this.i_modeName: str = a_modeName
			a_this.i_concernedPathToIsFoundMap: "OrderedDict [Path, bool]" = a_concernedPathToIsFoundMap
			a_this.i_writer: TextIO = a_writer
			a_this.i_isForOneOfConcernedPaths: bool = False
		
		def startDocument (a_this: "InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler") -> None:
			a_this.i_writer.write (GeneralConstantsConstantsGroup.c_lineFormat.format (XmlExpressionsConstantsGroup.c_xml1_0Declaration))
		
		def endDocument (a_this: "InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler") -> None:
			None
		
		def startElement (a_this: "InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler", a_elementName: str, a_attributes: AttributesImpl) -> None:
			try:
				l_pathString: Optional [str] = a_attributes.getValue (InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_pathAttributeName)
				l_path: Path = Path (l_pathString)
				if a_this.i_modeName == InDocumentPythonMacrosRegistrarConsoleProgram.c_addModeName:
					if a_this.i_concernedPathToIsFoundMap.get (l_path) is not None:
						a_this.i_isForOneOfConcernedPaths = True
						a_this.i_concernedPathToIsFoundMap [l_path] = True 
				else:
					l_concernedPath: Optional [Path] = None
					l_isFound: Optional [bool] = None
					# There is only one path in it.
					for l_concernedPath, l_isFound in a_this.i_concernedPathToIsFoundMap.items ():
						None
					if l_path == l_concernedPath or l_path.match ("{0:s}{1:s}{2:s}".format (str (l_concernedPath), GeneralConstantsConstantsGroup.c_linuxDirectoriesDelimiter, GeneralConstantsConstantsGroup.c_doubleAsterisks)):
						a_this.i_isForOneOfConcernedPaths = True
			except (KeyError) as l_exception:
				None
			if not a_this.i_modeName == InDocumentPythonMacrosRegistrarConsoleProgram.c_removeModeName or not a_this.i_isForOneOfConcernedPaths:
				a_this.i_writer.write (XmlDatumHandler.getElementOpenString (a_elementName, a_attributes))
		
		def endElement (a_this: "InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler", a_elementName: str) -> None:
			if a_elementName == InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_rootElementName and a_this.i_modeName == InDocumentPythonMacrosRegistrarConsoleProgram.c_addModeName:
				l_path: Optional [Path] = None
				l_isFound: Optional [bool] = None
				for l_path, l_isFound in a_this.i_concernedPathToIsFoundMap.items ():
					if not l_isFound:
						l_mediaTypeName: Optional [str] = None
						if not l_path.match (InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_pythonModuleFileGlobExpression):
							l_mediaTypeName = InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_binaryMediaTypeName
						else:
							l_mediaTypeName = InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_emptyMediaTypeName
						l_attributes: AttributesImpl = AttributesImpl ({InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_pathAttributeName: str (l_path), InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_mediaTypeAttributeName: l_mediaTypeName})
						a_this.i_writer.write (" {0:s}".format (GeneralConstantsConstantsGroup.c_lineFormat).format (XmlDatumHandler.getElementOpenString (InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_filePathElementName, l_attributes)))
						a_this.i_writer.write (" {0:s}".format (GeneralConstantsConstantsGroup.c_lineFormat).format (XmlDatumHandler.getElementCloseString (InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler.c_filePathElementName)))
			if not a_this.i_modeName == InDocumentPythonMacrosRegistrarConsoleProgram.c_removeModeName or not a_this.i_isForOneOfConcernedPaths:
				a_this.i_writer.write (XmlDatumHandler.getElementCloseString (a_elementName))
			a_this.i_isForOneOfConcernedPaths = False
		
		def characters (a_this: "InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler", a_contents: str) -> None:
			if not a_this.i_modeName == InDocumentPythonMacrosRegistrarConsoleProgram.c_removeModeName or not a_this.i_isForOneOfConcernedPaths:
				a_this.i_writer.write (a_contents)
	
	"""
	arguments:
	1 -> the file ingredients base directory path string
	2 -> the mode name: 'add' or 'remove'
	3 -> the target path string: if the mode name is 'remove' and this is empty, the 'Scripts' directory will be removed.
	"""
	@staticmethod
	def main (a_arguments: List [str]) -> None:
		if len (a_arguments) != 4:
			Publisher.logErrorInformation ("The arguments have to be these:\n1) the file ingredients base directory path string\n2) the mode name: 'add' or 'remove'\n3) the target path string: if the mode name is 'remove' and this is empty, the 'Scripts' directory will be removed.\n")
			exit GeneralConstantsConstantsGroup.c_errorResult
		l_fileIngredientsBaseDirectoryPath: Path = Path (a_arguments [1])
		l_modeName: str = a_arguments [2]
		if l_modeName != InDocumentPythonMacrosRegistrarConsoleProgram.c_addModeName and l_modeName != InDocumentPythonMacrosRegistrarConsoleProgram.c_removeModeName:
			Publisher.logErrorInformation ("The mode name has to be 'add' or 'remove'\n")
			exit GeneralConstantsConstantsGroup.c_errorResult
		
		l_targetPath: Path = Path (a_arguments [3])
		if l_modeName == InDocumentPythonMacrosRegistrarConsoleProgram.c_addModeName and l_targetPath == GeneralConstantsConstantsGroup.c_emptyString:
			Publisher.logErrorInformation ("The target path string cannot be empty for the 'add' mode\n")
			exit GeneralConstantsConstantsGroup.c_errorResult
		l_manifestFilePath: Path = l_fileIngredientsBaseDirectoryPath.joinpath (InDocumentPythonMacrosRegistrarConsoleProgram.c_manifestFileRelativePath)
		l_manifestModifiedFilePath: Path = l_fileIngredientsBaseDirectoryPath.joinpath (Path (GeneralConstantsConstantsGroup.c_fileNameFormat.format (str (InDocumentPythonMacrosRegistrarConsoleProgram.c_manifestFileRelativePath), FileNameSuffixesConstantsGroup.c_modifiedFileNameSuffix)))
		l_concernedPathToIsFoundMap: "OrderedDict [Path, bool]" = OrderedDict ()
		if l_modeName == InDocumentPythonMacrosRegistrarConsoleProgram.c_addModeName:
			l_concernedPathToIsFoundMap.update ({InDocumentPythonMacrosRegistrarConsoleProgram.c_pythonBaseDirectoryRelativePath.parent: False, InDocumentPythonMacrosRegistrarConsoleProgram.c_pythonBaseDirectoryRelativePath: False})
			l_path: Optional [Path] = None
			for l_path in reversed (l_targetPath.parents):
				if l_path != GeneralConstantsConstantsGroup.c_currentDirectoryPath:
					l_concernedPathToIsFoundMap.update ({InDocumentPythonMacrosRegistrarConsoleProgram.c_pythonBaseDirectoryRelativePath.joinpath (l_path): False})
		if l_targetPath != GeneralConstantsConstantsGroup.c_emptyString:
			l_concernedPathToIsFoundMap.update ({InDocumentPythonMacrosRegistrarConsoleProgram.c_pythonBaseDirectoryRelativePath.joinpath (l_targetPath): False})
		else:
			l_concernedPathToIsFoundMap.update ({InDocumentPythonMacrosRegistrarConsoleProgram.c_scriptsBaseDirectoryRelativePath: False})	
		l_saxParser: XMLReader = xml.sax.make_parser ( [DefaultValuesConstantsGroup.c_saxParserModuleName])
		l_saxParser.setFeature (xml.sax.handler.feature_namespaces, False)
		l_manifestFileReader: Optional [TextIO] = None
		l_manifestFileWriter: Optional [TextIO] = None
		try:
			l_manifestFileReader = cast (TextIO, open (l_manifestFilePath, FileOpenModeNamesConstantsGroup.c_readModeName))
			l_manifestFileWriter = cast (TextIO, open (l_manifestModifiedFilePath, FileOpenModeNamesConstantsGroup.c_eraseAndWriteModeName))
			l_manifestDatumParseEventsHandler: "InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler" = InDocumentPythonMacrosRegistrarConsoleProgram.ManifestDatumParseEventsHandler (l_modeName, l_concernedPathToIsFoundMap, l_manifestFileWriter)
			l_saxParser.setContentHandler (l_manifestDatumParseEventsHandler)
			l_saxParser.parse (l_manifestFileReader)
			os.remove (l_manifestFilePath)
			shutil.move (str (l_manifestModifiedFilePath), str (l_manifestFilePath))
		except (Exception) as l_exception:
			Publisher.logErrorInformation (l_exception)
			if l_manifestFileWriter is not None:
				l_manifestFileWriter.close ()
			if l_manifestFileReader is not None:
				l_manifestFileReader.close ()

if __name__ == GeneralConstantsConstantsGroup.c_pythonMainModuleName:
	InDocumentPythonMacrosRegistrarConsoleProgram.main (sys.argv)


theBiasPlanet/coreUtilities/constantsGroups/DefaultValuesConstantsGroup.py

@Python ソースコード

class DefaultValuesConstantsGroup:
	~
	c_saxParserModuleName: str = "xml.sax.expatreader"


theBiasPlanet/coreUtilities/constantsGroups/FileNameSuffixesConstantsGroup.py

@Python ソースコード

class FileNameSuffixesConstantsGroup:
	~
	c_pythonModuleFileNameSuffix: str = "py"
	~
	c_modifiedFileNameSuffix: str = "modified"


theBiasPlanet/coreUtilities/constantsGroups/FileOpenModeNamesConstantsGroup.py

@Python ソースコード

class FileOpenModeNamesConstantsGroup:
	c_readModeName: str = "r"
	c_eraseAndWriteModeName: str = "w"
	~


theBiasPlanet/coreUtilities/constantsGroups/GeneralConstantsConstantsGroup.py

@Python ソースコード
from pathlib import Path
import sys
from collections import OrderedDict
from theBiasPlanet.coreUtilities.constantsGroups.FileNameSuffixesConstantsGroup import FileNameSuffixesConstantsGroup

class GeneralConstantsConstantsGroup:
	~
	c_errorResult: int = -1
	~
	c_emptyString: str = ""
	~
	c_doubleAsterisks: str = "{0:s}{0:s}".format (c_asteriskCharacter)
	~
	c_linuxDirectoriesDelimiter: str = '/' # char
	~
	c_currentDirectoryPath: Path = Path (".")
	~
	c_fileNameFormat: str = "{{:s}}{:s}{{:s}}".format (c_fileNameElementsDelimiter)
	c_lineFormat: str = "{{:s}}{:s}".format (c_newLineCharacter)
	~
	c_pythonMainModuleName: str = "__main__"
	~


theBiasPlanet/coreUtilities/constantsGroups/XmlExpressionsConstantsGroup.py

@Python ソースコード

class XmlExpressionsConstantsGroup:
	c_xml1_0Declaration: str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
	~


'theBiasPlanet/coreUtilities/messagingHandling/Publisher.py'は、全体を省略します、なぜなら、使用されているメソッドは、ただログを書くだけなので。

theBiasPlanet/coreUtilities/xmlDataHandling/XmlDatumHandler.py

@Python ソースコード
from typing import List
from typing import Optional
import xml.sax.saxutils
from xml.sax.xmlreader import AttributesImpl
from theBiasPlanet.coreUtilities.constantsGroups.GeneralConstantsConstantsGroup import GeneralConstantsConstantsGroup

class XmlDatumHandler:
	@staticmethod
	def getElementOpenString (a_elementName: str, a_attributes: AttributesImpl) -> str:
		l_attributeStrings: List [str] = []
		l_attributeName: Optional [str] = None
		for l_attributeName in a_attributes.getNames ():
			l_attributeStrings.append ("{0:s}={1:s}".format (l_attributeName, xml.sax.saxutils.quoteattr (a_attributes.getValue (l_attributeName))))
		l_attributesString = " ".join (l_attributeStrings)
		return GeneralConstantsConstantsGroup.c_quotedByAngleBracketsFormat.format ("{0:s} {1:s}".format (a_elementName, l_attributesString))
	
	@staticmethod
	def getElementCloseString (a_elementName: str) -> str:
		return GeneralConstantsConstantsGroup.c_quotedByAngleBracketsFormat.format ("/{0:s}".format (a_elementName))


Objector 49B
. . .うん?それはどのように使えるの?

Hypothesizer 7
上記シェルスクリプトで、'vim "META-INF/manifest.xml"'を'bash -c "export PYTHONPATH=\"${PYTHONPATH}:/home/%user name%/myData/development/inDocumentPythonMacrosRegistrar/target:/home/%user name%/myData/development/coreUtilities/target\"; python3 -m theBiasPlanet.inDocumentPythonMacrosRegistrar.programs.InDocumentPythonMacrosRegistrarConsoleProgram \".\" \"${l_modeName}\" \"./${l_macroPackagePath}/${l_macroFileName}\""'で 置換すればよいだけです、もちろん、Pythonモジュール群パス群は、適切に設定されなければなりませんが。


3: テストする


Hypothesizer 7
当該ファイルをオープンして、当該Pythonマクロが実際にLibreOfficeまたはApache OpenOfficeによって認識されていることを見てみましょう、'Tools(ツール)' -> 'Macros(マクロ)' -> 'Run Macro...(マクロを実行)' -> '%the file name%' -> 'theBiasPlanet' -> 'pythonEnvironmentChecker' -> 'macros' -> 'PythonEnvironmentChecker' -> 'checkPythonEnvironment'と選択して。

Objector 49A
. . .おう、あるじゃん!動くのか?

Hypothesizer 7
もしも、マクロに問題なければ、もちろんです。


参考資料


<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>