目次
前
次
マクロ作成
マクロは、操作手順をBASICコードで表現して
自動で処理する「手続き」とみればよいでしょう。
マクロの作成は、プログラミングなので
操作手順を記録して、冗長な処理を削る
と考えると、理解しやすいです。
自分の経験では、高校の入学試験での合否判定を
自動化できないかと相談を持ち込まれたことで
マクロを知ることになりました。
spreadsheetとして、VisiCalcを知っていましたが
合否判定ではLotus1-2-3を使いました。
マクロ作成は、プログラミングなので、作成して
終了とはならずに、テストやデバッグが必要に
なります。
テストやデバッグで利用するツールは、以下。
BASICコードを、一気に動かしたり、1行ずつ
動かすためのツールが、アイコンで表示されて
います。
各アイコンに割り当てされた機能は、後で説明
しますが、マクロを作成したときは、使うこと
になると覚えておきましょう。
マクロは、BASICコードで記述します。
その一例は、以下。
REM ***** BASIC *****
Sub hello_world
' variables
Dim objS As Object
Dim xcar As String
Dim xcdr As String
Dim xstr As String
Dim xtmp As Integer
' substitute
xcar = "Hello"
xcdr = "World"
xtmp = 123
' concatenate
xstr = xcar & " , " & xcdr " ! "
' select target
objS = ThisComponent.CurrentController.ActiveSheet
' set pointer
ptr0 = objS.getCellRangeByName("A1")
ptr1 = objS.getCellRangeByName("B1")
' substitute
ptr0.String = xstr
ptr1.Value = xtmp
' message to User
MsgBox "Completed!"
End Sub
このマクロを実行すると、セルA1に文字列「Hello , World !」が
代入されます。
BASICで記述したマクロの内容からわかることをリスト。
- マクロは、SubとEnd Subで挟んだエリアに書き込む
- コメントは、REMか'の右に書いていく
- 利用する変数は、Dimを使って宣言
- 文字列変数に、文字列を格納するには、文字列を"で囲む
- 文字列を連結するには、&を使う
- 使いたいセルの指定には、シート番号とセル位置を書いていく
- シート番号の指定は、Sheets(i)を利用 iは、シート番号で0から始める
- セル位置の指定は、getCellByPosition(c,r)を利用 cは列、rは行を表す
- セルには、値、文字列の区別をして格納
マクロ作成では、何をしたいのかという仕様を
明らかにして、紙に手順を書出した後にコード
に変換すると、効率よく事が進んでいきます。
操作手順を紙に書出したら、その通りに操作します。
操作を記録させると、spreadsheetがBASICコードに
変換してくれます。
記録機能を利用し、spreadsheetにBASICコードを生成
させるのが、マクロを効率よく短時間で作成するコツ。
マクロを司るBASICコードの入力までの手順は、以下。
- マクロ記録ができるように、オプションで設定
- 「マクロの記録(A)」をクリック
- spreadsheetを操作して、一連の処理を入力
- 「記録の終了」をクリック
- 記録した処理を保存
この手順で作成したマクロに対応するBASICコードは
LibreOfficeBASICになります。
MicrosoftのExcelと同じにしたいときは
Option VBASupport
を入れておきます。
Option VBASupportは、マクロ記録では効力がないので
BASICコードを入力するときだけに限定されます。
例で用意したマクロは、VBAを使うと次のようになります。
REM ***** BASIC *****
Option VBAScript
Sub hello_world
' variables
Dim xcar As String
Dim xcdr As String
Dim xstr As String
Dim xtmp As Integer
' substitute
xcar = "Hello"
xcdr = "World"
xtmp = 123
' concatenate
xstr = xcar & " , " & xcdr " ! "
' set object to Cell
Cells(1,1).Value = xstr
Cells(1,2).Value = xtmp
' message to User
MsgBox "Completed!"
End Sub
VBAのマクロでは、Rangeで単独セルでも矩形領域指定の複数セルでも
処理できます。
CalcのBASICコードでは、getCellRangeByNameを利用。
ただし、ブックとシートの指定が必要です。
セルに入っている文字列を分割して、他のシートに格納する
マクロをExcelとCalcで作成して、相違を確認します。
対象となるspreadsheetのセルの内容は、以下。
セルB2からセルE3の中に入っている文字列を
分割していきます。
Sheet1のセルの内容を「/」で分割して
Sheet2に展開していくマクロを作成。
Excel
マクロ名を「MySplit」とします。
Dim xidx As String
Dim yidx As String
Dim zidx As String
Dim xstr As String
Dim ystr As String
Dim i As Byte
Dim xlen As Byte
Dim xcar As String
Dim xcdr As String
Sub MySplit()
' set pointer
sidx = 2
' clear cells
Sheets(sidx).Range("B2:I3").Value = ""
' loop
For i=0 to 7
' set pointer
Select Case i
Case 1 : xidx = "B3"
yidx = "B3"
zidx = "C3"
Case 2 : xidx = "C2"
yidx = "D2"
zidx = "E2"
Case 3 : xidx = "C3"
yidx = "D3"
zidx = "E3"
Case 4 : xidx = "D2"
yidx = "F2"
zidx = "G2"
Case 5 : xidx = "D3"
yidx = "F3"
zidx = "G3"
Case 6 : xidx = "E2"
yidx = "H2"
zidx = "I2"
Case 7 : xidx = "E3"
yidx = "H3"
zidx = "I3"
Case Else : xidx = "B2"
yidx = "B2"
zidx = "C2"
End Case
' get context
xstr = Range(xidx).Value
' split
xlen = len( xstr )
ystr = Right(xstr,7)
If xlen = 16 Then
xcar = Left(xstr,5)
Else
xcar = Left(xstr,4)
End if
xcdr = Left(ystr,4)
' store
Sheets(sidx).Range(yidx).Value = xcar
Sheets(sidx).Range(zidx).Value = xcdr
Next i
End Sub
Calc
Calcのマクロは、「Main」から始まるので、サブルーチンと
して呼び出すようにしておきます。
Dim objS As Object
Dim xstr As String
Dim ystr As String
Dim i As Byte
Dim j As Byte
Dim k As Byte
Dim ii As Byte
Dim sidx As Byte
Dim xlen As Byte
Dim xcar As String
Dim xcdr As String
Sub Main
MySplit
End Sub
Sub MySplit()
' set pointer
sidx = 1
' select object
objS = ThisComponent.CurrentController.ActiveSheet
' clear cells
For i=0 to 7
objS.Sheets(sidx).getCellByPosition(i+1,1).String = ""
objS.Sheets(sidx).getCellByPosition(i+1,2).String = ""
Next i
' outer loop
For i=0 to 7
' set pointer
j = i + 1
ptr0 = objS.Sheets(0).getCellByPosition(j,1)
ptr1 = objS.Sheets(0).getCellByPosition(j,2)
' calculate index
ii = 2 * i + 1
' inner loop
For k=0 To 1
' get context
xstr = ptr0.String
If k > 0 Then
xstr = ptr1.String
End If
' split
xlen = len( xstr )
ystr = Right(xstr,7)
If xlen = 16 Then
xcar = Left(xstr,5)
Else
xcar = Left(xstr,4)
End if
xcdr = Left(ystr,4)
' store
objS.Sheets(sidx).getCellByPosition(ii+0,k+1).String = xcar
objS.Sheets(sidx).getCellByPosition(ii+1,k+1).String = xcdr
Next ii
Next i
End Sub
Calcでは、getCellByPositionでセル位置を相対表現できるので
添字を使って、ターゲットとするセルの右と下をポインタで指定
して扱いやすくしました。
マクロを実行すると、次のように文字列が分割されます。
(項目名は、後から入力しています。)
Excel、Calcのマクロで、セルへ情報を出し入れするとき
大枠からより小さい範囲に絞っていきます。
Calcは、内部でJavaを利用しているのでクラス
インスタンスのメソッドで範囲を狭めていると
考えられます。
ここまでのマクロ定義では、情報が「/」で分けられていると
して扱っています。また、それぞれの情報の文字列長は固定と
して扱っています。
より汎用性のある処理にするため、InStr関数を利用して
書き換えてみます。
Excel
マクロ名を「MySplitX」とします。
Dim xidx As String
Dim yidx As String
Dim zidx As String
Dim xstr As String
Dim i As Byte
Dim i0 As Byte
Dim i1 As Byte
Dim i2 As Byte
Dim xcar As String
Dim xcdr As String
Sub MySplitX()
' set pointer
sidx = 2
' clear cells
Sheets(sidx).Range("B2:I3").Value = ""
' loop
For i=0 to 7
' set pointer
Select Case i
Case 1 : xidx = "B3"
yidx = "B3"
zidx = "C3"
Case 2 : xidx = "C2"
yidx = "D2"
zidx = "E2"
Case 3 : xidx = "C3"
yidx = "D3"
zidx = "E3"
Case 4 : xidx = "D2"
yidx = "F2"
zidx = "G2"
Case 5 : xidx = "D3"
yidx = "F3"
zidx = "G3"
Case 6 : xidx = "E2"
yidx = "H2"
zidx = "I2"
Case 7 : xidx = "E3"
yidx = "H3"
zidx = "I3"
Case Else : xidx = "B2"
yidx = "B2"
zidx = "C2"
End Case
' get context
xstr = Range(xidx).Value
' split
i0 = InStr(xstr,"rpm")
i1 = InStr(xstr,"/")
i2 = InStr(xstr,"deg")
xcar = Left(xstr,i0-1)
xcdr = Mid(xstr,jj+1,i2-i1-1)
' store
Sheets(sidx).Range(yidx).Value = xcar
Sheets(sidx).Range(zidx).Value = xcdr
Next i
End Sub
BASICでは、文字列の指定位置から部分文字列を
切り出すには、Mid関数を使うのが定石。
Calc
VBAとの差異があるところだけを書き直しておきます。
Dim objS As Object
Dim xstr As String
Dim i As Byte
Dim j As Byte
Dim k As Byte
Dim ii As Byte
Dim i0 As Byte
Dim i1 As Byte
Dim i2 As Byte
Dim sidx As Byte
Dim xcar As String
Dim xcdr As String
Sub Main
MySplitX
End Sub
Sub MySplitX()
' set pointer
sidx = 1
'
objS = ThisComponent.CurrentController.ActiveSheet
' clear cells
For i=0 to 7
objS.Sheets(sidx).getCellByPosition(i+1,1).String = ""
objS.Sheets(sidx).getCellByPosition(i+1,2).String = ""
Next i
' outer loop
For i=0 to 7
' set pointer
j = i + 1
ptr0 = objS.Sheets(0).getCellByPosition(j,1)
ptr1 = objS.Sheets(0).getCellByPosition(j,2)
' calculate index
k = 2 * i + 1
' inner loop
For ii=0 To 1
' get context
xstr = ptr0.String
If ii > 0 Then
xstr = ptr1.String
End If
' split
i0 = InStr(xstr,"rpm")
i1 = InStr(xstr,"/")
i2 = InStr(xstr,"deg")
xcar = Left(xstr,i0-1)
xcdr = Mid(xstr,i1+1,i2-i1-1)
' store
objS.Sheets(sidx).getCellByPosition(k+0,1+ii).String = xcar
objS.Sheets(sidx).getCellByPosition(k+1,1+ii).String = xcdr
Next ii
Next i
End Sub
目次
前
次