LibreOffice3.6で、配列変数をマクロで操作するには?

MSオフィスではsheetを操作すると時間がかかるので、Rangeを配列変数に入れて、配列変数上で必要な処理を済ませ、結果を配列からSheetRangeに値貼り付けをする方法を使っていました。LibreOfficeでシートRangeを変数に写し、変数を改めてシートRangeに貼り付ける方法はわかったのですが、http://openoffice3.web.fc2.com/OOoBasic_Calc.html#OOoCCI3c
配列変数(?)の要素にアクセスする方法がわかりません。添え字で指定しようとするとエラーになります。要素のデータの入手と書き換えはどのようにするのでしょう。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2012/11/17 18:11:16
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:taknt No.1

回答回数13539ベストアンサー獲得回数1198

ポイント400pt

エラーって何のエラーでしょう?

普通に oDisp = oDisp & oDF(i) みたいなことが できないってことですか?

他1件のコメントを見る
id:hathi

ありがとうございました。 
教えていただいたリンク先をみていくつかわかりました。 
 
どうも、結果的には、oCopyData = oCopyRange.getDataArray() や oCopyData = oCopyRange.getFormulaArray() で取り込んだ一見配列に見えるデータの塊は、個別に各要素を oCopyData(2,3)=230 のようにやるとエラーしたり、temp=oCopyData(3,1) では temp=oCopyData(3) と同じになったりしてしまうことがわかりました。 
どうやら、二段階で操作するしか方法がないようなので、それはそれで諦めます。
http://blog.livedoor.jp/addinbox/archives/51261348.html
また、oCopyData = oCopyRange.getFormulaArray() で取り込み、二段階方式で、oCopyDataの一部要素を書き換え、その後、 oPasteRange.setFormulAarray(oCopyData) とすれば、要素にあった数式も書き換えてもとのcellに数式としてセット出来ました。
これで、二段階方式ではあるけれども、所期の目的を達することが出来ることがわかりました。

ためしにつかったものは、下記です。
Sub Main6
Dim vntArray() As Variant
Dim vntTemp As Variant
ReDim vntArray(1 to 3,1 to 4)
vntArray(1,1) = "ABCD"
vntArray(2,1) = "******"
vntArray(3,2) = 12345
vntTemp = vntArray
vntArray(2,3) = "RTW"
vntTemp(2,1)="MMM"
VntTemp(3,4)=rnd()
VntTemp(3,2)=435
ReDim vntArray(1 to 3,1 to 4)
vntArray(1,4) = "XYZ"
VntTemp(1,2)=int(900*rnd())
vnttemp=vntarray
vntarray(1,2)=987
vnttemp(1,4)="KKK"
Redim preserve VntArray(1 to 3,1 to 4)
vntarray(1,3)="oiRF"
vnttemp(1,4)=876
redim vnrtemp()
temparea=thiscomponent.currentcontroller.activesheet.getcellrangebyposition(0,0,4,4)
dim vntp as variant
dim vntr as variant

vnttemp=temparea.getdataarray
vntp=temparea.getformulaarray
ggg=vntp(3) ' 配列相互は「代入」ではなく、参照になる ByRef
ggg(2)="=7+Int(Rand()*6)" ' これで代入すると、ggg(2)はvntp(3,2)に参照される
ggg(4)="" '
' vntp(3)=ggg ' これはなくて良い (既に参照されている)
vntR=vntp ' 動くが、同じObject配列が出来るのみ 
ggg=vntR(2) ' vntp と vntR は ByRefになるので、やっても意味がない
ggg(1)="文字列" '
' Redim preserve vntR(0 to 4,0 to 4) ' エラーになる
' vntp(3,2)="=5*4" ' こうしたアクセスは出来ない ' エラーになる
' drs=vntp(4,2) ' こうしたアクセスは出来ない ' drs=vntp(4) と同じになってしまう
'  (ユーザー定義型変数オブジェクトの構造体(?)は、普通の配列ではない)
temparea.setDataArray(vntp) ' エラーにはならないが、数式が文字列のようにセルに表示される
temparea.setDataArray(vntR) ' エラーにはならないが、数式が文字列のようにセルに表示される
temparea.setformulaarray(vntp) ' これで正常に(?)、数式は、指定エリアのセルに入る
' vntp の要素に文字としての数字があると、先頭に(')がついて、文字列になる
' MsgBox vntTemp(2,1) ' vntTmp(2,1) は、アクセスできない (構造体だから)
End Sub
 
ありがとうございました。
 

2012/11/17 18:09:59

その他の回答1件)

id:taknt No.1

回答回数13539ベストアンサー獲得回数1198ここでベストアンサー

ポイント400pt

エラーって何のエラーでしょう?

普通に oDisp = oDisp & oDF(i) みたいなことが できないってことですか?

他1件のコメントを見る
id:hathi

ありがとうございました。 
教えていただいたリンク先をみていくつかわかりました。 
 
どうも、結果的には、oCopyData = oCopyRange.getDataArray() や oCopyData = oCopyRange.getFormulaArray() で取り込んだ一見配列に見えるデータの塊は、個別に各要素を oCopyData(2,3)=230 のようにやるとエラーしたり、temp=oCopyData(3,1) では temp=oCopyData(3) と同じになったりしてしまうことがわかりました。 
どうやら、二段階で操作するしか方法がないようなので、それはそれで諦めます。
http://blog.livedoor.jp/addinbox/archives/51261348.html
また、oCopyData = oCopyRange.getFormulaArray() で取り込み、二段階方式で、oCopyDataの一部要素を書き換え、その後、 oPasteRange.setFormulAarray(oCopyData) とすれば、要素にあった数式も書き換えてもとのcellに数式としてセット出来ました。
これで、二段階方式ではあるけれども、所期の目的を達することが出来ることがわかりました。

ためしにつかったものは、下記です。
Sub Main6
Dim vntArray() As Variant
Dim vntTemp As Variant
ReDim vntArray(1 to 3,1 to 4)
vntArray(1,1) = "ABCD"
vntArray(2,1) = "******"
vntArray(3,2) = 12345
vntTemp = vntArray
vntArray(2,3) = "RTW"
vntTemp(2,1)="MMM"
VntTemp(3,4)=rnd()
VntTemp(3,2)=435
ReDim vntArray(1 to 3,1 to 4)
vntArray(1,4) = "XYZ"
VntTemp(1,2)=int(900*rnd())
vnttemp=vntarray
vntarray(1,2)=987
vnttemp(1,4)="KKK"
Redim preserve VntArray(1 to 3,1 to 4)
vntarray(1,3)="oiRF"
vnttemp(1,4)=876
redim vnrtemp()
temparea=thiscomponent.currentcontroller.activesheet.getcellrangebyposition(0,0,4,4)
dim vntp as variant
dim vntr as variant

vnttemp=temparea.getdataarray
vntp=temparea.getformulaarray
ggg=vntp(3) ' 配列相互は「代入」ではなく、参照になる ByRef
ggg(2)="=7+Int(Rand()*6)" ' これで代入すると、ggg(2)はvntp(3,2)に参照される
ggg(4)="" '
' vntp(3)=ggg ' これはなくて良い (既に参照されている)
vntR=vntp ' 動くが、同じObject配列が出来るのみ 
ggg=vntR(2) ' vntp と vntR は ByRefになるので、やっても意味がない
ggg(1)="文字列" '
' Redim preserve vntR(0 to 4,0 to 4) ' エラーになる
' vntp(3,2)="=5*4" ' こうしたアクセスは出来ない ' エラーになる
' drs=vntp(4,2) ' こうしたアクセスは出来ない ' drs=vntp(4) と同じになってしまう
'  (ユーザー定義型変数オブジェクトの構造体(?)は、普通の配列ではない)
temparea.setDataArray(vntp) ' エラーにはならないが、数式が文字列のようにセルに表示される
temparea.setDataArray(vntR) ' エラーにはならないが、数式が文字列のようにセルに表示される
temparea.setformulaarray(vntp) ' これで正常に(?)、数式は、指定エリアのセルに入る
' vntp の要素に文字としての数字があると、先頭に(')がついて、文字列になる
' MsgBox vntTemp(2,1) ' vntTmp(2,1) は、アクセスできない (構造体だから)
End Sub
 
ありがとうございました。
 

2012/11/17 18:09:59
id:oil999 No.2

回答回数1728ベストアンサー獲得回数320

ポイント100pt

http://q.hatena.ne.jp/1352728077#a1176781
にて誘導していただきましたので、こちらに回答いたします。

変数をDimで定義するときに、二次元配列の大きさを指定しないで済む方法


Dim ix() As Integer

のように空サイズの配列を宣言し、実行時に

ReDim ix(10, 5) As integer

のように配列の次元やサイズを自由に変更することができます。

id:hathi

ありがとうございます。
まだよくわかっていないのですが、ReDim の機能も少しわかりました。
http://blog.livedoor.jp/addinbox/archives/51261348.html
普通の配列だと、(1) vntTemp = vntArray は、代入ではなくて、各要素の値がvntTemp と vntArray とで、どちらからも相互にByRef(参照)になること、(2) ReDim で相互参照関係が切り離され、ReDim vntArray の場合は、ReDim vntArray の場合は、vntArrayの各要素がEmptyになるともわかりました。
 
今回やりたかったのは、質問に書いたようにsheetrangeを取り込んだ配列でObject変数になってしまいます。取り込んだ変数名をoCopyDataとすれば、temp=oCopyData のようにしても、tempもObject扱いになり、Redim や Redim preserve をしようとしてもうまく出来ませんでした。

2012/11/17 17:50:51
id:hathi

質問者から

hathi2012/11/18 23:26:49

おかげさまで、非常に高速で、20万行以上のデータ(ファイルサイズ17MB)を2分以内で処理(整理)できました。

書式を操作する、ユーザフォームを使うなどはしていないのでわかりませんが、データだけの簡単な操作ならば、MSオフィスでなくても、Libreでほぼ使えそうです。 助かります。

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません