質問する
0

4つのテキストボックスにある文字をBASICでつなぎたいのです。

質問日 2019-01-31 04:44:31 +0200

amada のGravatar画像

updated 2019-02-15 18:27:55 +0200

himajin100000 のGravatar画像

4つのテキストボックスにある文字をBASICでつなぎたいのです。
そして別のテキストボックスに表示したいです。

ふたつ悩んでます。
下記のコードを修正したいです。

===

質問①
下に記載したコードの左側に "@" をつけてます。
このひとつめの "@" のところで止まってしまいます。

  BASIC ランタイムエラー.
  '1'
  Type: com.sun.star.container.NoSuchElementException
  Message:

と表示されます。

===

質問②
CANCATの使用法と記述がわかりません。
ふたつめの "@" の場所に記載した内容で良いのでしょうか?

上記①の所で止まってしまうので、検証できてません。
あてずっぽうで書いたので、まるで自信がないです。

===

質問③
ほかに間違ってる所があれば教えてください。

===

   Sub ConcatAABBCCDD()

   Dim oForm As Object

   Dim oField1 As Object
   Dim oField2 As Object
   Dim oField3 As Object
   Dim oField4 As Object
   Dim oField5 As Object

   Dim document As Object
   Dim dispatcher As Object

   document = ThisComponent.CurrentController.Frame
   dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

   dispatcher.executeDispatch(document, ".uno:RecSave", "", 0, Array())
   dispatcher.executeDispatch(document, ".uno:RecRefresh", "", 0, Array())

   oForm = ThisComponent.Drawpage.Forms.getByName("ABCDフォーム")
   Doc = ThisComponent
   DocCtl = Doc.getCurrentController()

   oField1 = oForm.getByName("AA")

   oField2 = oForm.getByName("BB")

@   oField3 = oForm.getByName("CC")

   oField4 = oForm.getByName("DD")
   oField5 = oForm.getByName("EE")

@  AABBCCDD= concat(oField1.Text, oField2.Text, oField1.Text, oField4.Text)

   CtlView = DocCtl.GetControl(oPutField)
   CtlView.Text = AABBCCDD

   oField5.commit()

   dispatcher.executeDispatch(document, ".uno:RecSave", "", 0, Array())
   dispatcher.executeDispatch(document, ".uno:RecRefresh", "", 0, Array())

   End Sub

よろしくおねがいします。


edit retag flag offensive close merge delete

1 Answer

0

回答日 2019-01-31 12:58:39 +0200

himajin100000 のGravatar画像

updated 2019-02-01 08:48:49 +0200

当該コード、俺の環境でodbファイルのマクロから実行してみるも、DrawPageプロパティが見つけられずにエラーが出てます。odsファイル内のマクロから実行したりグラフから実行しているなら、XDrawPageSupplierがあるからわかるのですが…

Writerのときも、SwXTextDocumentがgetDrawPage()とgetDrawPages()の両方のメソッドを持つっぽい。なんでTextDocumentサービスにXDrawPagesSuppliersやXDrawPageSupplierがないのかはよくわからない。

実際、手元のodsファイルのマクロから、以下のコードが実行できてます。

oForm = ThisComponent.getSheets().getByName("Sheet1").DrawPage.Forms().getByName("Form1")

質問1 Type: com.sun.star.container.NoSuchElementExceptionってどういうエラー?

そのForm1にCCという名前のコントロールはちゃんと存在していますか?

質問2 Concat関数ってどうやって使うの?

StarBasicに存在する標準関数は、基本的に以下に載っている、インデントされていない部分にあるものだけだ。

https://opengrok.libreoffice.org/xref...

従ってConcat関数などという関数はStarBasicにはない。(表計算のCalcの数式の方にはある)

  • AbsはDouble型の引数を1つ取り、Double型の値を返す関数(FUNCTION_)。
  • Arrayはどうやら引数を取らないようだ。MS OfficeのArray関数って可変長引数っていう引数をいくつも並べられるものだった気がするが。
  • AscはString型の引数を1つ取り、Long型の値を返す関数。
  • AscWもString型の引数を1つ取り、Long型の値を返す関数。ただし、COMPATONLY_って書いてあるから、Option VBASupport 1が書かれていない場合は使用できない(…はずなんだけど、今手元で試したら再起動するまでVBASupport 1の効果が切れてなかった。なぜだろう(おぃ)
  • CallByNameは引数を3つ取ってVariant型の値を返す関数。

Asc関数はどんなことやる関数なのか、を調べる事もできる。

https://opengrok.libreoffice.org/xref...

プログラミング言語Cや同じくC++の知識がある人にはこれも見せておきたい

https://opengrok.libreoffice.org/xref...

そしてStarBasicにはJoin関数という、文字列連結用の関数が存在している。 https://opengrok.libreoffice.org/xref...

Sub Main()
    Dim x(2) As String
    x(0) = "a"
    x(1) = "b"
    x(2) = "c"
    Msgbox(Join(x,","))
End Sub

このコードは"a,b,c"に相当する文字列をダイアログに表示する。

今後 質問2に対する回答で優しく書きたいけど書けなさそうなことリスト(上級編)。

  • 以下の話は上記に載ってない関数とかに関わるCalcやWriterの話。今回のBaseには直接関係ないが、参考程度に。
  • .NETの標準ライブラリは、関数がそのまま存在するのではなく、メソッドは全てクラスに属するようになっている。VB6にあった関数の多くも結構な割合が静的メソッドとしてMicrosoft.VisualBasic名前空間の各種クラスに属すものになっている
  • 一般にこれらを使用するためには、クラス名.メソッド名(引数リスト)等と表記するが、初心者層が多いであろうこの言語に今までと少し変わった分類と書き方を習得させるのは少しハードルが高いとMSが思ったのか、.vbprojファイルに名前空間とクラス名を列挙しておくと、プログラマはそれらの記述を省略することが出来るようになっており、これによりVB6時代に近い書き方ができるようになっており、移行のハードルを下げようとした…のだろう。
  • StarBasicも基本的にこれらに似た手法を採っている。(上記の関数リストは確かstdObjだか何だかのメソッドとして登録されていた気がする。多分追調査はしないけど。)
  • CreateUNOService関数などでは、その引数にサービス名を指定するが、その時生成されるオブジェクトのC++上の名前は以下のような感じでLibreOfficeのコードに存在する。
    https://opengrok.libreoffice.org/xref...
  • Calcドキュメントにつけるマクロ上において、ooo.vba.excel.Globalsサービスに相当するオブジェクトは、Option VBASupport 1のときにのみVBAGlobalsという名前で参照できるが、この名前は省略することが出来、メソッドやプロパティ名から書き始めることが出来る。
  • ところで、どうやら、これらのメソッドやプロパティのうち、getやsetという小文字の文字列で始まるメソッドはgetやsetを除いた名前のプロパティとして使用できるようだ。どういう仕組みでそうなっているのかはわからないが。
  • そしてScVbaGlobalsには、getExcel()やgetActiveWorkbook()というメソッドが存在するのでExcelやActiveWorkbookという書き出し方ができる
    https://opengrok.libreoffice.org/xref...

余談 そこまでわかってて、https://ask.libreoffice.org/ja/question/179181/に回答しない理由は何?

  • 先に述べた議論と同様、GetObject()という関数は存在しない。
  • MS OfficeのVBAと同様、外部のDLLの関数を呼ぶ機能は存在する。
  • Ole32.dllにCoGetObject関数が存在する
    https://docs.microsoft.com/en-us/wind...
  • MS Officeは32ビット版と64ビット版が存在はしているものの、多分多くのエンドユーザが使っているのは32ビット版。そして、32ビット版と64ビット版では若干書き方が異なる。
  • LibreOfficeも32ビット版と64ビット版が存在するんだけど、 DLLの呼び出し方は変わるだろうか?
  • 「動いていること」は「安全なコードを書いた」ことと同値ではない。低レイヤ層に行けば行くほどそうなる。
  • その辺を安全に検証できるか自分の力量に自信がなく怖気づいている。
edit flag offensive delete link もっと

Comments

暇人さん。いつもありがとうございます。
どうしようもない私にお付き合いくださって、感謝しています。

====

ご返答ありがとうございます。ほっとしています。
以前の質問に対して全くレスがつかないままなので心配してました。

====
ひとつめ
====

で、、これ↓ですが、
フォームで実施する「レイアウト作業」にとんでもないバグ?があるみたいです。

---------

最初、暇人さんからの以下の返信を見て

com.sun.star.container.NoSuchElementExceptionってどういうエラー?
そのForm1にCCという名前のコントロールはちゃんと存在していますか?

やっぱりそうなんだぁ。。だったのです。

oField1 = oForm.getByName("AA")
oField2 = oForm.getByName("BB")

までは止まらないのに、

oField3 = oForm.getByName("CC")

で止まってしまうので、何度も確認し、
もう最後には、"CC"の部分をまるままコピペして貼り付けてみたのですが、
やっぱりここで、止まってしまいます。

ですので自分の解釈(←どこにも教科書が無いので解釈です)が間違っているのかな。。
と思って質問してみたのですが。原因がまるで掴めませんでした。

で。頂いた返事を見てから、昨夜、もう一度見てみたら、コントトールの名前が
「テキストボックス1(←数字だけバラバラ)」に初期化されていたのです。

???と思って修正したのですが、ふと気がついて以下のことを試しました。

amada のGravatar画像amada ( 2019-02-01 02:16:28 +0200 )edit

フォーム内のレイアウトを修正するとき、
ラベルフィールドと、テキストボックスフィールドをグループ化して移動しますよね?
でないと、ひとつひとつ動かさねばならず、グチャグチャになります。

これやると、つまりグループ化をすると、
フィールドの名前が強制的に初期化されてしまうのです。

いろいろ試しましたが、テキストボックスの場合は、
必ず全てで再現するわけではなく、約半数のテキストボックスがそうなります。

ですが再現するテキストボックスは、何度試しても必ず初期化されます。
今回の場合、"AA" "BB" は初期化されず、"CC" が初期化されていました。

何度試しても、"CC" だけ、必ず名前が初期化されてしまいます。
他にもたくさんありましたが、マクロを設定しない限りは普通に動きます。

最悪なのはチェックボックスです。ほぼ100%初期化されます。
探せば同じ症状のコントロールが他にもあるかもしれません。

いずれにしても、フォーム内のコントロールのグループ化をすべて解除し
消えていたコントロールの名前をつけ直したら、ここは通るようになりました。

amada のGravatar画像amada ( 2019-02-01 02:19:11 +0200 )edit

====
ふたつめ
====
結局、うんうんと言いながら徹夜してしまいました。
文字の接続が、わかりません。

少しいじると、別のエラーが発生する繰り返しです。
わからないことだらけで降参です。教えてください。

現在は以下の状態です。
"AA" "BB" "CC" "DD" を空間無しで繋いで
"AABBCCDD" を oField4 に貼り付けたいです。

以下の左側 "@" で止まります。

BASIC ランタイムエラー.
'380'
プロパティ値が正しくありません。

と出ます。

デバッグがそこで止まるのと、
その先のデバッグの仕方がまるでわからず、"@"以下の行は検証できていません。

------------

amada のGravatar画像amada ( 2019-02-01 02:21:02 +0200 )edit

------------

Sub ConcatAABBCCDD()

Dim oForm As Object

Dim oField0 As Object
Dim oField1 As Object
Dim oField2 As Object
Dim oField3 As Object
Dim oField4 As Object

Dim document As Object
Dim dispatcher As Object

document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

dispatcher.executeDispatch(document, ".uno:RecSave", "", 0, Array())
dispatcher.executeDispatch(document, ".uno:RecRefresh", "", 0, Array())

oForm = ThisComponent.Drawpage.Forms.getByName("ABCDフォーム")
Doc = ThisComponent
DocCtl = Doc.getCurrentController()

oField0 = oForm.getByName("AA")
oField1 = oForm.getByName("BB")
oField2 = oForm.getByName("CC")
oField3 = oForm.getByName("DD")

oField4 = oForm.getByName("EE")

Dim AaBbCcDd As Object
Dim AaBbCcDdText(3) As String

amada のGravatar画像amada ( 2019-02-01 02:22:46 +0200 )edit

@ AaBbCcDdText(0) = oField0
AaBbCcDdText(1) = oField1
AaBbCcDdText(2) = oField2
AaBbCcDdText(3) = oField3

AaBbCcDd = Join(AaBbCcDdText,"")

CtlView = DocCtl.GetControl(oField0, oField1, oField2, oField3, oField4)
CtlView.Text = AaBbCcDdText

dispatcher.executeDispatch(document, ".uno:RecSave", "", 0, Array())
dispatcher.executeDispatch(document, ".uno:RecRefresh", "", 0, Array())

End Sub


==========

よろしくおねがいします。

amada のGravatar画像amada ( 2019-02-01 02:23:29 +0200 )edit

ふたつめ

多分、型が違う

Dim AaBbCcDd As String ' 型をStringに変更
Dim AaBbCcDdText(3) As String

AaBbCcDdText(0) = oField0.Text
AaBbCcDdText(1) = oField1.Text
AaBbCcDdText(2) = oField2.Text
AaBbCcDdText(3) = oField3.Text

AaBbCcDd = Join(AaBbCcDdText,"")
CtlView.Text = AaBbCcDd '代入する変数を変更

だとどうです?あ、これらoField0とかはテキストボックスだと仮定しています。

MS OfficeのVBAだと、多分各コントロールにデフォルトプロパティが設定されていて、今回の代入文など、演算がオブジェクトの型を要求しないために処理が実行できないときは、そのデフォルトプロパティが利用されたものとして再度評価を行うような仕組みがあります。(文法からそのオブジェクト自身に対する演算なのか、デフォルトプロパティの内容に対する演算なのか判断できなくなってしまうため、VB6にはSet構文やIs演算子が必要になっているわけですね。VB.NETでも移行する者たちのため多分こういうものは使えるようになっていますが、デフォルトプロパティを前提としない設計を中心にしているせいか、これらの構文を全く使わなくても大丈夫なようになっているはずです) VBAからStarBasicに移行する人たちのためか、Option VBASupport 1のとき、一部だけ使えるようにしているのですが、StarBasicではこれらのコントロールにはデフォルトプロパティが設定されていないようです。個人的には初心者に媚びへつらっただけの悪い機能だと思っており、毎回ちゃんとTextプロパティを参照する形で書くことを勧めたいです。

himajin100000 のGravatar画像himajin100000 ( 2019-02-01 04:57:08 +0200 )edit

これやると、つまりグループ化をすると、 フィールドの名前が強制的に初期化されてしまうのです。

気分に余裕のあるときに検証してみたいです。

以前の質問に対して全くレスがつかないままなので

自分は単純に答えがわからなかったんです。odsやodtのときは当該構文で出来るようなんですけどね… 実は一回手元で成功したんですが、その際IDEがクラッシュしてしまい、復元されてきたものに、成功したコードが含まれておらず、かつ、そのコードを再び書き上げることが出来ず、調査が難航しています。

himajin100000 のGravatar画像himajin100000 ( 2019-02-01 05:04:37 +0200 )edit

あ、これらoField0とかはテキストボックスだと仮定しています。

↓↓ ご推察のとおりです。
全てテキストボックスです。

実は、教えていただいた以下ですが、既に試していました。
それでも同じ場所で止まってしまうのです。

DimAaBbCcDdAsString' 型をStringに変更
Dim AaBbCcDdText(3) As String AaBbCcDdText(0) = oField0.Text AaBbCcDdText(1) = oField1.Text AaBbCcDdText(2) = oField2.Text AaBbCcDdText(3) = oField3.Text AaBbCcDd = Join(AaBbCcDdText,"") CtlView.Text = AaBbCcDd '
代入する変数を変更

これで出てくるメッセージは以下です。

BASIC ランタイムエラー.
'423'
Text
amada のGravatar画像amada ( 2019-02-01 20:52:32 +0200 )edit

ちなみにエラーメッセージは変わっています。
型が Object のままだと、エラーメッセージは以下です。

BASIC ランタイムエラー.
'380'
プロパティ値が正しくありません。


ここで、更に試したことがあります。
Option VBASupport 1 をREMしてみました。

以下のようにメッセージ文が変わります
まさか、、Textプロパティ?メソッドが、無い???
なんてことは考えにくいと思うのですが。。

REM Option VBASupport 1 すると。
正しくありません。→見つかりません。に変わったのです???
BASIC ランタイムエラー. 次のプロパティまたはメソッドが見つかりません: Text。

もう諦めたほうが良いのでしょうか??
繰り返しますが、何をやっても「同じ行」で止まります。 エラーメッセージが変わるだけです。

amada のGravatar画像amada ( 2019-02-01 20:56:19 +0200 )edit

自分はOption VBASupport 1は外して物事を考えることが多いです。今の実装だとエラーメッセージではなくエラー番号が出てしまいますし、前述のデフォルトプロパティのせいで本来の原因とは違うエラーメッセージが表示されたりして厄介なので。

次のプロパティまたはメソッドが見つかりません: Text

LibreOffice自体のC++のコードを読んだわけではありませんが、このプロパティが見つからないということは、「自分がその変数に代入されているものがテキストボックスだ誤解しているが、実は違うものが入っている」可能性があると考えてます。

自分なら、oField0をウォッチウィンドウに放り込んで中身を確認してみます。SupportedServiceNamesやImplementationNameが何になっているのか確認するわけですね。まぁ文字列とかだったらそのプロパティとかはないわけですが。

また、再現する最小限のファイルが作れ、個人情報等を含まず、俺に見られてもいいファイルを準備できるなら、そのファイルをどこかにアップロードして、「ちょっとhimajin100000さんや、実際のファイル提供するから再現するか、した場合何が原因か調べてくれんかのう?」という風にするのもアリです。まぁ解決できる保証はできないのですが。

himajin100000 のGravatar画像himajin100000 ( 2019-02-01 21:24:12 +0200 )edit
ログイン/サインアップして回答する

質問ツール

2 followers

Stats

Asked: 2019-01-31 04:44:31 +0200

Seen: 111 times

Last updated: Feb 02