人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

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

●質問者: hathi
●カテゴリ:コンピュータ
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● きゃづみぃ
●400ポイント ベストアンサー

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

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


hathiさんのコメント
申し訳ありません。検討不足でした。次のようなコードで、とりあえず自分がねらっていた目的は、とりあえず達成できました。 Sub oCopyData ' 範囲のデータをコピーし、それを貼り付ける (書式は写らない) Dim oDoc as Object Dim oSheet1, oSheet2 as Object Dim oCopyData as Object Dim oCopyRange as Object Dim oPasteRange as Object Dim test2 as Object Dim GG as variant Dim sCol, eCol as Long Dim sRow, eRow as Long oDoc = ThisComponent oSheet1 = oDoc.getSheets().getByIndex(0) oSheet2 = oDoc.getSheets().getByIndex(1) sCol = 0 :eCol = 14 :sRow = 0 :eRow = 10 oCopyRange = oSheet1.getCellRangeByPosition(sCol, sRow, eCol, eRow) oPasteRange = oSheet2.getCellRangeByPosition(sCol, sRow, eCol, eRow) test2 = oSheet1.getCellRangeByPosition(sCol+2, sRow+6, eCol+2, eRow+6) oCopyData = oCopyRange.getDataArray() GG = "khmじ" GG=345 GG=oCopyData(2) hY=gg(6) gg(3)="置換データ" gg(2)=int(rnd()*400)+0.77 oCopyData(2)=gg oPasteRange.setDataArray(oCopyData) test2.setDataArray(oCopyData) End Sub ところで、上記の方法では、二次元のObjectの配列の一次元の要素(一行分のデータ)をVariant変数に入れて、そのVariantの要素をアクセスして、結果のVariant変数を、二次元のObjectの配列の一次元の要素に写すという方法になっています。 これでも便利なときはありますが、直接二次元の要素をアクセスする方法はあるのでしょうか。 oDFはsheetのRangeから転写した内容だとして、次のようなことを可能に出来るのでしょうか。 oDF(i,j) = oDF(i+3,j) + oDF(i+4,j-1)* CC

きゃづみぃさんのコメント
http://hermione.s41.xrea.com/pukiwiki/pukiwiki.php?OOobbs%2F28 http://oooug.jp/faq/index.php?faq%2F6%2F221

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 ありがとうございました。

2 ● oil999
●100ポイント

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

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


Dim ix() As Integer

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

ReDim ix(10, 5) As integer

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


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 をしようとしてもうまく出来ませんでした。

質問者から

おかげさまで、非常に高速で、20万行以上のデータ(ファイルサイズ17MB)を2分以内で処理(整理)できました。
書式を操作する、ユーザフォームを使うなどはしていないのでわかりませんが、データだけの簡単な操作ならば、MSオフィスでなくても、Libreでほぼ使えそうです。 助かります。


関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ