2019年9月22日日曜日

18: LibreOfficeをファイルコンバータとして最適に用いる(C++実装)

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

OpenDocument/Microsoft Office/等フォーマット間で、PDF/CSVフォーマットへ、高速かつ万能に、ドキュメントを調整することも可能。動かせるサンプルあり。

話題


About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: C++

この記事の目次


開始コンテキスト



ターゲットコンテキスト



  • 読者は、C++にてUNO APIを直接に用いてファイルコンバージョンを実装する方法を理解し、動かせるサンプルを得る。

オリエンテーション


本シリーズの任意のサンプルプログラムをビルドする方法の記事があります。

LibreOfficeまたはApache OpenOfficeデーモンを作成する方法の記事があります。

LibreOfficeまたはApache OpenOffice Microsoft Windowsサービスを作成する方法の記事があります。

オフィスファイルをオープニングパスワードでUNOを用いて暗号化する方法の記事があります。

OpenDocumentファイルに編集パスワードをUNOを用いてセットすることについての記事があります。

バイナリWord/Excelファイルに編集パスワードをUNOを用いてセットすることについての記事があります。

Office Open XMLファイルに編集パスワードをUNOを用いてセットすることについての記事があります。

ワードプロセッサドキュメントのページのサイズをUNOを用いてセットすることについての記事があります。

スプレッドシートドキュメントのページのサイズをUNOを用いてセットすることについての記事があります。

ワードプロセッサドキュメントの任意のページプロパティをUNOを用いてセットすることについての記事があります。

スプレッドシートドキュメントの任意のページプロパティをUNOを用いてセットすることについての記事があります。

任意のオフィスドキュメントをPDFファイルとしてフル仕様指定でUNOを用いてエクスポートすることについての記事があります。

任意のスプレッドシートをCSVへ任意のフォーマットでUNOを用いて書き出すことについての記事があります。

任意のスプレッドシートドキュメントの全スプレッドシートをCSVファイル群へUNOを用いて書き出すことについての記事があります。


本体

ト書き
Special-Student-7、Morris(C++プログラマー )、Chloe(C++プログラマー)がコンピュータの前にいる。


0: 注意: 'soffice --convert-to' は決して使いません


Special-Student-7
本記事のコンセプトパートが読まれているものと想定されていることは明確に述べられているものの、読者の内のかなりの割合が読んでいないし読まないだろうことが推測でき、多くの人々が'soffice --convert-to'を使うことに固執している事実を鑑みて、念押しすることが適切だろうと感じて申しますが、ここでは、'soffice --convert-to'は決して使われません。

その理由は、コンセプトパートに詳述されています。


1: UNO APIを用いたファイルコンバージョンロジックの実装


Special-Student-7
知っておく必要のあることは本記事のコンセプトパートから既にご存知であると想定して、UNO APIを用いたファイルコンバージョンロジックのC++実装をすぐに見ましょう、ここで、'l_underlyingRemoteUnoObjectsContextInXComponentContext'はLibreOfficeまたはApache OpenOfficeインスタンスへのUNOオブジェクト群コンテキスト、'l_originalFileUrl'は元ファイルのURL、'l_targetFileUrl'はターゲットファイルのURL、'l_fileStoringFilterName'はファイル格納フィルター名です。

@C++ ソースコード
// header Start
#ifndef __theBiasPlanet_unoUtilitiesTests_fileConvertingTest1_Test1Test_hpp__
	#define __theBiasPlanet_unoUtilitiesTests_fileConvertingTest1_Test1Test_hpp__
	
	#include <optional>
	#include <regex>
	#include <com/sun/star/util/URL.hpp>
	
	using namespace ::std;
	
	namespace theBiasPlanet {
		namespace unoUtilitiesTests {
			namespace fileConvertingTest1 {
				class Test1Test {
					private:
						static regex const c_urlRegularExpression;
						static ::com::sun::star::util::URL getUrlInURL (string const & a_url);
					public:
						static int main (int const & a_argumentsNumber, char const * const a_argumentsArray []);
				};
			}
		}
	}
#endif

// header End

// source source Start
#include "theBiasPlanet/unoUtilitiesTests/fileConvertingTest1/Test1Test.hpp"
#include <iostream>
#include <com/sun/star/beans/PropertyState.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/frame/XStorable2.hpp>
#include <com/sun/star/frame/XSynchronousDispatch.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/util/XCloseable.hpp>
~
#include "theBiasPlanet/unoUtilities/stringsHandling/UnoExtendedStringHandler.hpp"
~

using namespace ::std;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;
~
using namespace ::theBiasPlanet::unoUtilities::stringsHandling;
~

namespace theBiasPlanet {
	namespace unoUtilitiesTests {
		namespace fileConvertingTest1 {
			// the 'com.sun.star.util.URLTransformer' UNO service can be used if you want to, as I do this manually.
			::com::sun::star::util::URL Test1Test::getUrlInURL (string const & a_url) {
				OUString const l_urlInOUString (UnoExtendedStringHandler::getOustring (a_url));
				OUString const l_emptyInOUString;
				int l_portNumber = 0;
				string::const_iterator l_urlIteratorAtStart (a_url.cbegin ());
				string::const_iterator l_urlIteratorAtEnd (a_url.cend ());
				smatch l_regularExpressionMatcher;
				if (regex_search (l_urlIteratorAtStart, l_urlIteratorAtEnd, l_regularExpressionMatcher, c_urlRegularExpression)) {
					OUString const l_protocolInOUString (UnoExtendedStringHandler::getOustring (l_regularExpressionMatcher [1]));
					OUString const l_pathInOUString (UnoExtendedStringHandler::getOustring (l_regularExpressionMatcher [2]));
					return ::com::sun::star::util::URL (l_urlInOUString, l_urlInOUString, l_protocolInOUString, l_emptyInOUString, l_emptyInOUString, l_emptyInOUString, l_portNumber, l_pathInOUString, l_emptyInOUString, l_emptyInOUString, l_emptyInOUString);
				}
				return ::com::sun::star::util::URL (l_urlInOUString, l_urlInOUString, l_emptyInOUString, l_emptyInOUString, l_emptyInOUString, l_emptyInOUString, l_portNumber, l_emptyInOUString, l_emptyInOUString, l_emptyInOUString, l_emptyInOUString);
			}
			
			int Test1Test::main (int const & a_argumentsNumber, char const * const a_argumentsArray []) {
				~
						string l_originalFileUrl (a_argumentsArray [3]);
						string l_targetFileUrl (a_argumentsArray [4]);
						string l_fileStoringFilterName (a_argumentsArray [5]);
						
						string l_com_sun_star_frame_theDesktopSingletonUrl ("/singletons/com.sun.star.frame.theDesktop");
						Reference <XDispatchProvider> l_underlyingUnoDesktopInXDispatchProvider (* ( (Reference <XInterface> *) (l_underlyingRemoteUnoObjectsContextInXComponentContext->getValueByName (UnoExtendedStringHandler::getOustring (string ("/singletons/com.sun.star.frame.theDesktop"))).getValue ())), UNO_QUERY);
						Reference <XSynchronousDispatch> l_underlyingFileOpeningUnoDispatcherInXSynchronousDispatch (l_underlyingUnoDesktopInXDispatchProvider->queryDispatch (getUrlInURL ("file:///"), UnoExtendedStringHandler::getOustring (string ("_blank")), -1), UNO_QUERY);
						
						::com::sun::star::util::URL l_originalFileUrlInURL (getUrlInURL (l_originalFileUrl));
						Sequence <PropertyValue> l_unoDocumentOpeningPropertiesSequence (4);
						l_unoDocumentOpeningPropertiesSequence [0] = PropertyValue (UnoExtendedStringHandler::getOustring (string ("ReadOnly")), -1, Any (true), PropertyState_DIRECT_VALUE);
						l_unoDocumentOpeningPropertiesSequence [1] = PropertyValue (UnoExtendedStringHandler::getOustring (string ("Hidden")), -1, Any (true), PropertyState_DIRECT_VALUE);
						l_unoDocumentOpeningPropertiesSequence [2] = PropertyValue (UnoExtendedStringHandler::getOustring (string ("OpenNewView")), -1, Any (true), PropertyState_DIRECT_VALUE);
						l_unoDocumentOpeningPropertiesSequence [3] = PropertyValue (UnoExtendedStringHandler::getOustring (string ("Silent")), -1, Any (true), PropertyState_DIRECT_VALUE);
						Sequence <PropertyValue> l_unoDocumentStoringPropertiesSequence (2);
						l_unoDocumentStoringPropertiesSequence [0] = PropertyValue (UnoExtendedStringHandler::getOustring (string ("FilterName")), -1, Any (UnoExtendedStringHandler::getOustring (l_fileStoringFilterName)), PropertyState_DIRECT_VALUE);
						l_unoDocumentStoringPropertiesSequence [1] = PropertyValue (UnoExtendedStringHandler::getOustring (string ("Overwrite")), -1, Any (true), PropertyState_DIRECT_VALUE);
						::com::sun::star::uno::Any l_underlyingOriginalUnoDocumentInAny (l_underlyingFileOpeningUnoDispatcherInXSynchronousDispatch->dispatchWithReturnValue (l_originalFileUrlInURL, l_unoDocumentOpeningPropertiesSequence));
						bool l_hasSucceeded (false);
						if (l_underlyingOriginalUnoDocumentInAny.hasValue ()) {
							Reference <XStorable2> l_underlyingOriginalUnoDocumentInXStorable2 (* ( (Reference <XInterface> *) (l_underlyingOriginalUnoDocumentInAny.getValue ())), UNO_QUERY);
							try {
								l_underlyingOriginalUnoDocumentInXStorable2->storeToURL (UnoExtendedStringHandler::getOustring (l_targetFileUrl), l_unoDocumentStoringPropertiesSequence);
								l_hasSucceeded = true;
							}
							catch (exception const & l_exception) {
								throw l_exception;
							}
							Reference <XCloseable> (l_underlyingOriginalUnoDocumentInXStorable2, UNO_QUERY)->close (false); 
						}
						else {
							cout << string ("### The original file: '") << l_originalFileUrl << string ("' cannot be opened.") << endl << flush;
						}
				~
			}
		}
	}
}

// source source End

Chloe
. . . ふーむ、十分にシンプルね。

Morris
同感だ。そのシンプルなコードで問題だという奴はC++プログラマーとは言えんな。

Special-Student-7
注意として、その"UnoExtendedStringHandler::getOustring"は私のユーティリティクラスメソッドで、'::rtl::OUString'(UNO stringのC++マッピング)のインスタンスを生成するものです。そのような説明コードではそうしたユーティリティクラスは基本的には使わないことにしているのですが、そのメソッドは例外です、というのは、'::rtl::OUString'インスタンスを生成するのは、各説明コードで示すには面倒すぎるからです(面倒だというのは、UTF-8からUTF-16へのコンバージョンを行わなければならないからです)。あなたは、その私のユーティリティクラスメソッドを使う必要はありませんし、また、そのユーティリティクラスは後ほど紹介される私のサンプルに含まれています。

Morris
それは、以前記事でもう聞いたよ。

Special-Student-7
もしも、うまくいかないという方がおられたら、多分それは、UNOオブジェクト群コンテキストを取得することについてでしょうが、それは、ある記事(単にまたは用意周到な方法用)にて説明されています。

上記コードは、まさに、本記事のコンセプトパートのあるセクションにて申し上げたことを行なっています: 元ファイルをオープンする、オープンされたドキュメントをターゲットフォーマットにて格納する、オープンされたドキュメントをクローズする。

'dispatchWithReturnValue'が元ファイルをオープンして、'storeToURL'がオープンされたドキュメントを格納して、'close'がオープンされたドキュメントをクローズしています。

'l_underlyingFileOpeningUnoDispatcherInXSynchronousDispatch'は、あるUNOディスパッチャであり、ファイル毎に取得する必要はありません。

可能なフィルター名たちは、本記事のコンセプトパートに挙げられています。


2: オープンするまたは格納することに対するプロパティ群について


Special-Student-7
上記コードに見られるとおり、ファイルをオープンすることに対していくつかのプロパティをセットすることができます。実のところ、以下が、可能なプロパティ群の仕様です、ここで、データタイプはC++タイプです(UNOタイプではなく)。注意として、各データは、実際には、'::com::sun::star::uno::Any'インスタンスでラップしなければなりません。

名前データタイプ説明
ReadOnlyboolオープンされたドキュメントを元ファイルに書き戻せないかどうか: 'true'-> できない、'false'-> できる
Hiddenboolオープンされたドキュメントは不可視かどうか: 'true'-> 不可視、'false'-> 不可視でない
OpenNewViewboolwhether the document is opened in a new view: 'true'-> in a new view, 'false'-> not in a new view ドキュメントは新たなビュー内にオープンされるかどうか: 'true'-> 新たなビュー内に、'false'-> 新たなビュー内にではない
Silentboolドキュメントはサイレントにオープンされるかどうか: 'true'-> サイレントに、'false'-> サイレントにではない
Password::rtl::OUStringオープニングパスワード

関心を持たれるかもしれないプロパティに、オープニングパスワードがあります。

Chloe
それじゃあ、オープニングパスワードでプロテクトされたファイルをコンバートできるのね。

Special-Student-7
ご注意いただきたいのですが、UNO 'string'は公式には'null'を受け入れません、したがって、もしもオープニングパスワードがなければ、プロパティ自体、指定すべきではありません、'null'が偶然受け入れられることはあるかもしれませんが。

これもご注意いただきたいのですが、'ReadOnly'は、オープンされたドキュメントが編集できないことを意味せず、そのドキュメントは元ファイルへ書き戻せないことを意味します、したがって、ドキュメントが調整されて新たなファイルへ書かれるのに、それが'false'である必要はありません。

ドキュメントを格納することに対しても、いくつかのプロパティをセットすることができます。実のところ、以下が、可能なプロパティ群の仕様です、ここで、データタイプはC++タイプです(UNOタイプではなく)。注意として、各データは、実際には、'::com::sun::star::uno::Any'インスタンスでラップしなければなりません。

名前データタイプ説明
FilterName::rtl::OUStringフィルター名
FilterData場合による一部のフィルターに対するフィルター特有のデータ: 常にというわけではないが、しばしば'com.sun.star.beans.PropertyValue'の配列
FilterOptions::rtl::OUString一部のフィルターに対するフィルター特有のデータ
AsTemplateboolドキュメントがテンプレートとして格納されるかどうか: 'true'-> テンプレートとして、'false'-> テンプレートとしてではない
Author::rtl::OUString著者名
DocumentTitle::rtl::OUStringドキュメントタイトル
EncryptionDatacom.sun.star.beans.NamedValue []一部のフィルターに対する暗号化データ
Password::rtl::OUString一部のフィルターに対するオープニングパスワード
CharacterSet::rtl::OUString文字セット
Versionshortバージョン番号
Comment::rtl::OUStringバージョン記述
Overwriteboolファイルが上書きされるかどうか: 'true' -> 上書きされる、'false' -> 上書きされない
ComponentData場合による一部のフィルター特有データ: 常にというわけではないが、しばしば'com.sun.star.beans.NamedValue'の配列
ModifyPasswordInfo場合による一部のフィルターに対する編集パスワードデータ

オープニングパスワードは実のところ暗号化データに他なりません。なぜ、'EncryptionData'と'Password'の両方があるかという理由は、一部のフィルターは一方を使い、他の一部のフィルターは他方を使うことです。詳細は、別の記事をご参照ください。

編集パスワードをセットすることに関する事情はかなり複雑です: 編集パスワードは、フォーマット特有のアルゴリズムでハッシュ化されなければならず、ハッシュは、フォーマット特有の場所へセットされなければならず、場所は必ずしもファイル格納プロパティ群の中ではありません。 . . . 詳細は、OpenDocumentファイル用Microsoftバイナリファイル用Office Open XMLファイル用のある記事に説明されています。

Morris
えーと、俺は個人的には編集パスワードがそんな面倒に値するとは思わん、なぜなら、それは、悪意ある改ざんに対するセキュリティ対策というよりも、単に不注意にファイルを編集してしまわないためのものだが、俺は、そんなに不注意な奴らに同情しないから。

Special-Student-7
それは、あり得るポリシーだと私は思います、しかし、いずれにせよ、私の動かせるサンプルはそのロジックを実装してあるので、それを使われる方がいてもいいでしょう、もしも、そういうつもりがあれば。

'FilterData'や'FilterOptions'のような"フィルター特有"プロパティたちに具体的に何がセットできるかということについては、ファイルコンバージョンの一般的ロジックのためのものである本記事では説明できません: PDFファイル用CSVファイル用といった、いくつかの他の記事をご参照ください。 .


3: ドキュメントを調整することについて


Special-Student-7
ターゲットファイルは、ファイル格納プロパティ群を介してのみでは満足のいくようにコントロールされないかもしれません。

その場合は、オープンされたドキュメントを調整することができます。

Chloe
ふむ、その"l_underlyingOriginalUnoDocumentInXStorable2"UNOオブジェクトを介して、オープンされたドキュメントが調整できるというのは理解してるけどね、理論的には、ということだけど。

Special-Student-7
具体的にどのように調整できるかは、勿論ドキュメント特有、要件特有であって、いくつかの他の記事、例えば、ワードプロセッサドキュメントのページプロパティ群を調整するためのもの(ここおよびここ)やスプレッドシートドキュメントのページプロパティ群を調整するためのもの(ここおよびここ)をご参照ください。本シリーズ内でもっと語るつもりです。


4: 動かせるサンプルがここにあります


Special-Student-7
ある動かせるサンプルがここからダウンロード可能です。

そのサンプルプログラムは、引数の1つとして、ファイルコンバージョン命令群を格納したJSONファイルのパス(実のところ、複数のJSONファイルパスを取れます)を取り、それらの命令を実現します。

JSONファイルの仕様は以下のとおりです。

@JSON ソースコード
[
	{Disabled: %本レコードが無効化されているか否か -> 'true'または'false'%, 
	OriginalFileUrl: %元ファイルURL、その中では任意のオペレーティングシステム環境変数を使用できる、'%{HOME}'のように%, 
	TargetFileUrl: %ターゲットファイルURL、その中では任意のオペレーティングシステム環境変数を使用できる、'%{HOME}'のように%, 
	FileStoringFilterName: %ファイル格納フィルター名%, 
	OpeningPassword: %元ファイルに対するオープニングパスワード%, 
	Title: %ターゲットファイルタイトル%, 
	EncryptingPassword: %ターゲットファイルに対する暗号化パスワード%, 
	EditingPassword: %ターゲットファイルに対する編集パスワード%, 
	CertificateIssuerName: %ターゲットファイルに署名するための証明書発行者名%, 
	CertificatePassword: %ターゲットファイルに署名するための証明書パスワード%, 
	SignatureTimeStampAuthorityUrl: %ターゲットファイルに署名するためのタイムスタンプオーソリティURL%, 
	DocumentTailorNames: [%ドキュメントテイラー名%, . . .], 
	AllSpreadSheetsAreExported: %全スプレッドシートがエクスポートされるか否か: 'true'または'false'%, 
	TargetFileNamingRule: %ターゲットCSVファイル群に対する命名規則: '0'-> 各CSVファイルはシートインデックスを使って命名される、'1'-> 各CSVファイルはシート名を使って命名される%, 
	CsvItemsDelimiterCharacterCode: %CSV項目間デリミタの文字コード: 例えば、'44'-> ','%, 
	CsvTextItemQuotationCharacterCode: %CSVテキスト項目クォーテーションの文字コード: 例えば、'34'-> '"'%, 
	CsvCharactersEncodingCode: %CSV文字群エンコーディングコード: '76' -> UTF-8、'65535' -> UCS-2、'65534' -> UCS-4、'11' -> US-ASCII、'69' -> EUC_JP、'64' -> SHIFT_JIS%, 
	CsvAllTextItemsAreQuoted: %全てのCSVテキスト項目がクウォートされるか否か: 'true'または'false'%, 
	CsvContentsAreExportedAsShown: %CSVコンテンツがシート上に表示されているとおりにエクスポートされるか否か: 'true'または'false'%, 
	CsvFormulaeThemselvesAreExported: %シートセルフォーミュラ自体がCSVファイルへエクスポートされるか否か: 'true'または'false'%, 
	HiddenSpreadSheetsAreExported: %非表示スプレッドシートもエクスポートされるか否か%}, 
	. . .
	{. . .}
]

Morris
"テイラー"?そんな用語は覚えてないな。

Special-Student-7
"テイラー"は、私が発明した用語で、ドキュメントを特定の方法にて調整する任務を帯びたオブジェクトを意味します。

Morris
それじゃあ、自分で何か作れということだな。

Special-Student-7
私はいくつかのサンプルテイラーを用意しましたが、はい、特定のニーズをお持ちでしたら、ご自分でお作りになる必要があるでしょう。

Morris
まあ、見てみよう。

Chloe
クラス名を指定するってこと?

Special-Student-7
いいえ、オブジェクト名です: 1つのクラス由来の複数のテイラーがあるかもしれません、それぞれ違うパラメータでコンストラクトされた。

命令がそうしたファイルから来るのではなく、Webリクエストのようなものから来る場合は、各命令をメモリ内JSONレコードに構成して、そのJSONレコードを、'executeConversionOrder'メソッドに渡すことができます。

もしも、JSONレコードに追加の機能が必要でしたら、あなたは、'executeConversionOrder'メソッドを'FileConversionOrderExtendedJsonDatumParseEventsHandler' JSON解析イベント群ハンドラと共に変更することができます。

サンプルは複数の命令群ファイルを受け付けるようにしてあり、それらのファイルは同時実行で処理されます、その目的は、この最適な方法では、コンバージョンは同時実行で行なえることをデモンストレーションすることです。


4-1: サンプルプロジェクトをビルドする


Special-Student-7
サンプルプロジェクトをビルドする方法は、ある記事に説明されています。

特に、注意すべきは、プロジェクト群は、いくつか別のプログラミング言語による実装も含んでおり、それらは、C++プログラマーであるあなたは多分必要としないだろうということです。そうした不要なコードを無視する方法はそこに説明されています。

メインプロジェクトは'filesConverter'です。


4-2: サンプルプログラムを実行する


Special-Student-7
サンプルプログラムを実行する前に、LibreOfficeまたはApache OpenOfficeインスタンスを、それがクライアントからのコネクションを受け付けるように開始しておかなければなりません、ある以前の記事にて学んだ方法によって。

ト書き
Special-Student-7は、LibreOfficeインスタンスをポート番号2002で開始する。

Special-Student-7
コンバージョン命令群JSONファイルが必要です(上に挙げられた仕様で)で、私たちは、アーカイブファイルに'filesConverter/data/FileConversionOrders.json'として含まれているサンプルJSONファイルを使用しますが、少なくとも、その中のファイルURL群は調整しなければなりません。

サンプルプログラムは以下のように実行できます、カレントディレクトリをサンプルプロジェクトディレクトリに位置させて。

@cmd ソースコード
gradle i_executeCplusplusExecutableFileTask -Pi_commandLineArguments="\"socket,host=localhost,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext\" \"data/FileConversionOrders.json\""

ト書き
Special-Student-7は、上記コマンドを、ターミナル内でカレントディレクトリをサンプルプロジェクトディレクトリに位置させて実行する。

Special-Student-7
もしも、LibreOfficeまたはApache OpenOfficeインスタンスがリモートホストにいるのであれば、ホスト名は'localhost'から変えればよいだけです、もしも、ファイアウォールが通信をブロックしないのであればですが、勿論。

そして、以下のように複数のJSONファイルを指定することができます。

@cmd ソースコード
gradle i_executeCplusplusExecutableFileTask -Pi_commandLineArguments="\"socket,host=localhost,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext\" \"data/FileConversionOrders.json\" \"data/FileConversionOrders2.json\""


4-3: サンプルコードを理解する


Special-Student-7
注意として、サンプルコードは私のユーティリティプロジェクト('coreUtilitiesToBeDisclosed'および'unoUtilitiesToBeDisclosed')を使っており、それらは、直接にはファイルコンバージョンの作業に関係していないコードを含んでいます。それらユーティリティプロジェクトの無関係な部分のみを取り去るのはそれほど容易でないことをご理解ください、コードは関連しあっているので。

ファイルコンバージョンロジックは、'::theBiasPlanet::unoUtilities::filesConverting::FilesConverter'クラスの'convertFile'メソッド(CSVファイルへコンバートするためのものを除き)または'convertSpreadSheetsDocumentFileToCsvFiles'メソッド(CSVファイルへコンバートするためのもの)内にあり、メソッドは、ドキュメントテイラー群とファイル格納プロパティ群を取ります、いくつか他のものに加えて。

新たなドキュメントテイラーをインストールするためには、当該クラスを'::theBiasPlanet::unoUtilities::documentsHandling::UnoDocumentTailor'の子として、そのクラスのインスタンスを一意な名前で、'::theBiasPlanet::filesConverter::programs::FilesConverterConsoleProgram'クラスの'l_unoDocumentTailorNameToUnoDocumentTailorMap'変数へ登録しなければなりません。


参考資料


  • Apache OpenOffice Wiki. (2014/01/02). Apache OpenOffice Developer's Guide. Retrieved from https://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide
<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>