OpenOffice.org Basicでガントチャート
OpenOffice.org Basicを使ってガントチャート作成用マクロ ガントチャートforOOoを開発する手順を紹介していきます。
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
Elie_World 無料ソフト

Elie_Schedule_OOo Ver 1.0.1

僕と同様にOpenOffice.orgを使ってガントチャートを描画するマクロを公開しているサイトがあります。とは言え、こちらの方が先発で歴史が古いようです。
このマクロ作者である山村氏も僕と同じようにExcel(Office)VBAでの開発も行われていて、他にも多くのツールを公開されています。

僕のようにVBAとOOoBasicでガントチャート1本というのではやはり弱いなと感じているので、このようにいくつもマクロを公開するべきだと考えています。ですが、実務でExcelもOpenOffice.orgも使わなくなってきて、社内Webアプリ開発ばかりやっているのではネタもなかなか見つからない。

これは非常にもったいないと思います。
世の中には「作りたくても作れない人」がたくさんいるのに、「作れるけど何を作るかわからない人」もいるのです。誰かが「こんなの欲しい!」と書き込むと、それを読んだ人が「こんなんでどうでしょう」と要望に合わせたマクロ(コードを示すんじゃなくて、動作する完成品)を作ってくれる...そんなコミュニティーサイトがあっても良いかなって思いますね。このブログが一段落したら作ってみようかな。

なんだかとりとめの無いコラムになってしまいましたが、興味のある方は一度上記サイトを訪ねてみてはいかがでしょうか?

スポンサーサイト

テーマ:OpenOffice.org - ジャンル:コンピュータ

工程編集ダイアログ その1

IDEにて「BASIC ダイアログ」を挿入し、名称を「dlgEditSchedule」とします。そして、データ編集に必要なコントロールを配置すると下図のようになります。
ここで、chkCalendarというチェックボックスがありますが、これは日付のデータをカレンダーを使って入力できるようにするための工夫です。これは後に説明するカレンダーダイアログが完成してから補足する事にします。


次に、このダイアログを操作するためにモジュールを挿入し、名称を「mdlEditSchedule」とします。
このモジュールでのダイアログの操作を簡便にするため、ダイアログと登録した全コントロール用の変数を宣言し、初期化処理にてそれを割り当てます。
また、ボタンを押した時の処理もマクロ内で割り当てるためActionLestener用変数、色設定用のMouseListener用変数も宣言します。

下記にコードの一部を示し、各部の説明を行います。

Option Explicit

Private oDialog As Object '---(1)
 
Private lblId As Object '---(2)
Private lblName As Object
Private lblPlan As Object
Private lblAct As Object
Private lblLineType As Object
Private lblWeight As Object
 
Private txtId As Object
Private txtName As Object
Private txtPlanBegin As Object
Private txtPlanEnd As Object
Private imgPlanColor As Object
Private txtActBegin As Object
Private txtActEnd As Object
Private imgActColor As Object
Private lstLineType As Object
Private txtWeight As Object
 
Private chkCalendar As Object
Private btnOK As Object
 
Public dlgEditSchedule_Title As String
Public dlgEditSchedule_lblId_Text As String
Public dlgEditSchedule_lblName_Text As String
Public dlgEditSchedule_lblPlan_Text As String
Public dlgEditSchedule_lblAct_Text As String
Public dlgEditSchedule_lblLineType_Text As String
Public dlgEditSchedule_lblWeight_Text As String
Public dlgEditSchedule_chkCalendar_Label As String
Public dlgEditSchedule_btnOK_Label As String
Public dlgEditSchedule_PlanColor As String
Public dlgEditSchedule_ActColor As String
 
Private oActionListener As Object '---(3)
Private oMouseListener As Object
 
Private Id As Integer '---(4)
Private flgUpdate As Boolean '---(5)
Private flgCalendar As Boolean
 
Public Function Show(TargetId As Integer) As Boolean '---(6)
    
    flgUpdate = False
    
    Id = TargetId
    If Id < 1 Or mdlSchedule.Count < Id Then Exit Function
    
    Initialize
    setValues(Schedules(Id))
    With oDialog
        .execute
        .dispose
    End With
    
    Show = flgUpdate
    
End Function
 
Private Sub Initialize '---(7)
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgEditSchedule)
    
    With oDialog
        .Title = dlgEditCategory_Title
        lblId = .getControl("lblId")
        lblName = .getControl("lblName")
        lblPlan = .getControl("lblPlan")
        lblAct = .getControl("lblAct")
        lblLineType = .getControl("lblLineType")
        lblWeight = .getControl("lblWeight")
        
        txtId = .getControl("txtId")
        txtName = .getControl("txtName")
        txtPlanBegin = .getControl("txtPlanBegin")
        txtPlanEnd = .getControl("txtPlanEnd")
        imgPlanColor = .getControl("imgPlanColor")
        txtActBegin = .getControl("txtActBegin")
        txtActEnd = .getControl("txtActEnd")
        imgActColor = .getControl("imgActColor")
        lstLineType = .getControl("lstLineType")
        txtWeight = .getControl("txtWeight")
        
        chkCalendar = .getControl("chkCalendar")
        btnOK = .getControl("btnOK")
    End With
    
    oActionListener = CreateUnoListener("dlgEditScheduleActionListener_", _
        "com.sun.star.awt.XActionListener") '---(8)
    oMouseListener = CreateUnoListener("dlgEditScheduleMouseListener_", _
        "com.sun.star.awt.XMouseListener")
    
    lblId.Text = dlgEditSchedule_lblId_Text
    lblName.Text = dlgEditSchedule_lblName_Text
    lblPlan.Text = dlgEditSchedule_lblPlan_Text
    lblAct.Text = dlgEditSchedule_lblAct_Text
    lblLineType.Text = dlgEditSchedule_lblLineType_Text
    lblWeight.Text = dlgEditSchedule_lblWeight_Text
    
    imgPlanColor.addMouseListener(oMouseListener)
    imgActColor.addMouseListener(oMouseListener)
    
    txtPlanBegin.addMouseListener(oMouseListener)
    txtPlanEnd.addMouseListener(oMouseListener)
    txtActBegin.addMouseListener(oMouseListener)
    txtActEnd.addMouseListener(oMouseListener)
    
    lstLineType.AddItem(LineType_Line_Text,0) '---(9)
    lstLineType.AddItem(LineType_Rectangle_Text,0)
    lstLineType.AddItem(LineType_Default_Text,0)
    
    chkCalendar.Label = dlgEditSchedule_chkCalendar_Label
    
    btnOK.setLabel(dlgEditSchedule_btnOK_Label)
    btnOK.addActionListener(oActionListener)
    
End Sub

各部の解説を行います

  1. ダイアログおよび各コントロール用変数の宣言
  2. 表示初期化用変数の宣言
  3. アクションリスナー用変数の宣言
  4. 編集中のデータを認識するためのIDを保存する変数を宣言
  5. データの更新を行ったか否かを保存するための変数を宣言
  6. ダイアログ表示用の関数で、編集したい分類IDを引数とします
  7. ダイアログ初期化用関数
  8. 本ダイアログ用のアクションリスナー生成
  9. 線の種類をリストボックスから選択するための項目追加

次に、表示初期化用変数をmdlMain内のInitialize関数にて定義します。

mdlMainのInitialize関数に追記

    dlgEditSchedule_Title = "工程編集"
    dlgEditSchedule_lblId_Text = ControlLabelString("ID")
    dlgEditSchedule_lblName_Text = ControlLabelString("名称")
    dlgEditSchedule_lblPlan_Text = ControlLabelString("予定")
    dlgEditSchedule_lblAct_Text = ControlLabelString("実績")
    dlgEditSchedule_lblLineType_Text = ControlLabelString("線種")
    dlgEditSchedule_lblWeight_Text = ControlLabelString("人数")
    dlgEditSchedule_chkCalendar_Label = ControlLabelString("カレンダーを使用")
    dlgEditSchedule_btnOK_Label = ControlLabelString("設定")
    dlgEditSchedule_PlanColor = "予定線色"
    dlgEditSchedule_ActColor = "実績線色"

このまま実行すると、各種Listener用の関数が正しく定義されていないので、エラーになります。もし、試しに動作させたい場合は、リスナーを追加する行をコメントアウトしてみて下さい。

テーマ:OpenOffice.org - ジャンル:コンピュータ

色選択ダイアログ その3

最後に各種リスナー用の動作を設定します。

スクロールバーで青を調整する時の動作は、

Private Sub scbBlue_Changed
    setColors
End Sub

となり、この関数を呼び出すために

Private Sub dlgSelectColorAdjustmentListener_adjustmentValueChanged(oEvent)
    scbBlue_Changed
End Sub
Private Sub dlgSelectColorAdjustmentListener_disposing(): End Sub

とします。AdjustmentListenerには「adjustmentValueChanged」と「disposing」の2つを作成する必要があります。

次に、サンプル色をクリックした時にimgSelectedの背景色を変更する処理は下記となります。

Private Sub imgPalette_mousePressed(oEvent As Object)

    imgSelected.getModel().BackgroundColor = _
        oEvent.Source.getModel().BackgroundColor
    
End Sub

これを呼び出すためのマウスリスナーを設定すると

Sub dlgSelectColorMouseListener_mousePressed(oEvent As Object)
    imgPalette_mousePressed(oEvent)
End Sub
Sub dlgSelectColorMouseListener_disposing(): End Sub
Sub dlgSelectColorMouseListener_mouseReleased(oEvent): End Sub
Sub dlgSelectColorMouseListener_mouseEntered(oEvent): End Sub
Sub dlgSelectColorMouseListener_mouseExited(oEvent): End Sub

となります。MouseListenerは、「mousePressed」「disposing」「mouseReleased」「mouseEntered」「mouseExited」を作成する必要があります。

最後に各ボタンの動作を設定します。
全てのボタンを押してダイアログを終了するのですが、btnOKなら特にすることはなく、btnCancelならばimgBaseの背景色をimgSelectedに写し、btnNoColorならば背景色無しを意味する-1を設定してダイアログを閉じます。

Private Sub dlgSelectColorActionListener_actionPerformed(oEvent)
    Select Case oEvent.Source.getModel.Name
        Case "btnOK"
            
        Case "btnCancel"
            imgSelected.getModel.BackgroundColor = _
                imgBase.getModel.BackgroundColor
        Case "btnNoColor"
            imgSelected.getModel.BackgroundColor = -1
    End Select
    oDialog.endExecute
End Sub
Private Sub dlgSelectColorActionListener_disposing(): End Sub

このダイアログは色々なところで活躍します。今後、工程の設定や環境設定で利用していきたいと思います。

テーマ:OpenOffice.org - ジャンル:コンピュータ

色選択ダイアログ その2

色の番号を取得するためにRGBを用いると前回書きましたが、RGBについて少し説明します
色の表現方法はたくさんあります(参考URL)が、RGBは赤、緑、青の濃度を0~255の数値を使って表現する手法で256 x 256 x 256 = 16777216色を表現する事ができます。RGBという名称は3色の頭文字をとったものです。

RGBでは赤は16711680、緑は65280、青は255ですが、これらの数値を覚えることはとてもできませんので、これを取得するRGB関数があります。これは各色を0~255で指定することで、対応した数値を返してくれます。
例えば、赤の値を取得するには以下のように書きます。

RGB(255, 0, 0)
緑であれば、
RGB(0, 255, 0)
となります。

dlgSelectColorでは、パレットに使用するイメージボックスが5x5しかないので、RGBで表現できる全ての色を使うのは無理があります。そこで、各色を5段階とし、5x5x5の125色を扱うことになります。よって、scbBlueの最大値は4とします。

scbBuleの現在値から青色の濃度を計算し、imgPaletteの色を順番に指定していきます。ここで、左上から右に進むと赤の濃度が増え、下に進むと緑が増えることとします。
これをプログラムで表現すると下記となります。

Private Sub setColors

    Dim i As Integer
    Dim Blue As Integer
    
    Blue = scbBlue.Value * 255 / 4
    
    For i = 0 To UBound(imgPalette())
        imgPalette(i).getModel().BackgroundColor = _
            RGB((i mod 5) / 4 * 255, Int(i / 5) / 4 * 255, Blue)
    Next i
    
End Sub

ちなみに、modとは割り算の余りを取得するために用います。

テーマ:OpenOffice.org - ジャンル:コンピュータ

色選択ダイアログ その1

ガントチャートforExcelでは、色を自由に設定できるようにします。
工程データには予定と実績の色情報を持たせていますし、休日の色分けもできるようにする予定ですが、色を直接入力させるようにしたのでは使い勝手が良くありません。
そこで、色をダイアログで確認しながら選択できるような機能を作りたいと思います。

まず、ダイアログの名称を「dlgSelectColor」とし、デザインは下図となります。


左側の5x5の四角はイメージボックスでImageControl1~25まで連番で名前をつけています。右側の2つは同じくイメージボックスでimgBaseとimgSelectedとしました。また、スクロールバーはscbBlueとします。

このダイアログの動作は、5x5個のイメージボックスにサンプル色を表示し、imgBaseに元の色を表示します。そして、サンプル色のイメージボックスをクリックするとimgSelectedに選択色を表示し、設定を押すと選択した色の番号が取得できるというものにします。また、色はRGBで指定するため、赤(R)と緑(G)を使ってサンプル色を生成し、青(B)はscbBlueを使って変化させることにします。
まず、これまでと同様にコントロール用の変数を作成し、表示と初期化用のマクロを作成します。この時、ボタンやイメージのクリック、スクロールバーの調整にリスナーを割り当てるので、3種類のリスナーを宣言します。下記にコードを示します。

mdlSelectColor

Option Explicit
 
Private oDialog As Object
 
Private imgPalette(24) As Object '---(1)
Private imgBase As Object
Private imgSelected As Object
Private scbBlue As Object
Private btnOK As Object
Private btnCancel As Object
Private btnNoColor As Object
 
Public dlgSelectColor_btnOK_Label As String
Public dlgSelectColor_btnCancel_Label As String
Public dlgSelectColor_btnNoColor_Label As String
 
Private oActionListener As Object '---(2)
Private oMouseListener As Object
Private oAdjustmentListener As Object
 
Public Function Show(Title As String, BaseColor As Long) As Long
    
    Initialize(BaseColor)
    
    With oDialog
        .Title = Title
        .execute
        Show = imgSelected.getModel.BackgroundColor '---(3)
        .dispose
    End With
    
End Function
 
Private Sub Initialize(BaseColor As Long)
    
    Dim i As Integer
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgSelectColor)
    
    With oDialog
        btnOK = .getControl("btnOK")
        btnCancel = .getControl("btnCancel")
        btnNoColor = .getControl("btnNoColor")
        imgBase = .getControl("imgBase")
        imgSelected = .getControl("imgSelected")
        scbBlue = .getControl("scbBlue")
    End With
    
    imgBase.getModel().BackgroundColor = BaseColor '---(4)
    imgSelected.getModel().BackgroundColor = BaseColor
    
    oActionListener = CreateUnoListener("dlgSelectColorActionListener_", _
        "com.sun.star.awt.XActionListener")
    oMouseListener = CreateUnoListener("dlgSelectColorMouseListener_", _
        "com.sun.star.awt.XMouseListener")
    oAdjustmentListener = CreateUnoListener("dlgSelectColorAdjustmentListener_", _
        "com.sun.star.awt.XAdjustmentListener")
    
    btnOK.addActionListener(oActionListener)
    btnCancel.addActionListener(oActionListener)
    btnNoColor.addActionListener(oActionListener)
    
    btnOK.Label = dlgSelectColor_btnOK_Label
    btnCancel.Label = dlgSelectColor_btnCancel_Label
    btnNoColor.Label = dlgSelectColor_btnNoColor_Label
    
    For i = 0 To UBound(imgPalette())
        imgPalette(i) = oDialog.getControl("ImageControl" & (i+1)) '---(5)
        With imgPalette(i)
            .addMouseListener(oMouseListener)
        End With
    Next i
    
    scbBlue.addAdjustmentListener(oAdjustmentListener)
    
    setColors '---(6)
    
End Sub

各部の詳細を説明します。

  1. ImageControl1~25を格納する変数です。ここでは一つ一つ宣言するのではなく、配列で指定します。配列は0から数えるので、5x5 - 1で24を指定します。
  2. 動作に合わせて、3種類のリスナーを宣言しておきます。
  3. ダイアログを終了する時、imgSelectedの背景色を戻り値とします。
  4. 表示の時に指定した色をimgBaseとimgSelectedに指定しておきます。
  5. ImageConrol1~25をimgPaletteに格納し、マウスリスナーを割り当てます。
  6. 次回、この関数について説明を行います。

そして、mdlMainのInitialize関数に下記を追加します。

    dlgSelectColor_btnOK_Label = ControlLabelString("設定")
    dlgSelectColor_btnCancel_Label = ControlLabelString("キャンセル")
    dlgSelectColor_btnNoColor_Label = ControlLabelString("無色")

テーマ:OpenOffice.org - ジャンル:コンピュータ

データ編集ダイアログ作成サポートダイアログ

データを編集するダイアログの作成方法は、ほぼ決まっています。
必須項目を挙げると

  1. 変数宣言の強制 Option Explicit
  2. ダイアログ用変数、コントロール用変数の宣言
  3. コントロール表示用の文字列変数宣言
  4. 初期化関数内での各種変数へのコントロール割当
  5. コントロールの値をデータと同期させる
です。
そこで、これらの処理を半自動的に作成するモジュールを作成します。

まず、テキストフィールドのみをもつダイアログを作成し、dlgTextとします。
ダイアログは下図のようになります。ここで、テキストフィールドに複数行を入力/表示可能としておくため、複数行を「はい」に設定しておきます。

次に、mdlTextというモジュールを追加して、このダイアログを表示するためのコードを書きます。

mdlText

Option Explicit
 
Sub Show(myText As String)
    
    Dim oDialog As Object
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgText)
    
    With oDialog.getControl("TextField")
        oDialog.Model.Width = .Model.Width
        oDialog.Model.Height = .Model.Height
        .Text = myText
    End With
    
    With oDialog
        .execute
        .dispose
    End With
    
End Sub

ダイアログを宣言して、テキストフィールドに合わせてダイアログの大きさ調整を行ってから引数のテキストをテキストフィールドに割り当てると言う単純なものです。
このダイアログは結構便利なので、僕はよく使います。

次に、前述の編集ダイアログ開発手順に従ってダイアログ操作用のコードを生成するコードを書きます。

mdlText

Sub MakeDialogModuleTemplete(oDialog As Object)
    
    Dim myCode As String
    
    Dim oControls
    Dim DialogName As String
    
    Dim i As Integer
    Dim wk(6) As String
    
    Dim sName As String
    Dim sType As String
    
    oControls = oDialog.Controls
    DialogName = oDialog.getModel.Name
    
    myCode = "Option Explicit" & chr(13) & _
        "Private oDialog As Object" & chr(13)
    
    For i = 0 To UBound(oControls)
        
        'oControlModel = oControls(i).getModel
        sName = oControls(i).getModel.Name
        
        Select Case oControls(i).ImplementationName
            Case "stardiv.Toolkit.UnoButtonControl", _
                "stardiv.Toolkit.UnoCheckBoxControl"
                sType = "Label"
            Case Else
                sType = "Text"
        End Select
        
        wk(0) = wk(0) & chr(13) & "Private " & sName & " As Object"
        wk(1) = wk(1) & chr(13) & "Public " & DialogName & "_" & _
            sName & "_" & sType & " As String"
        wk(2) = wk(2) & chr(13) & chr(9) & chr(9) & _
            sName & " = .getControl("""& sName & """)"
        
        wk(3) = wk(3) & chr(13) & chr(9) & sName & "." & sType & _
            " = " & DialogName & "_" & sName & "_" & sType
        
        wk(4) = wk(4) & chr(13) & chr(9) & _
            DialogName & "_" & sName & "_" & sType & _
            " = ControlLabelString("""")" 
        
        wk(5) = wk(5) & chr(13) & chr(9) & chr(9) & _
            sName & ".Text" & _
            " = ._" & Right(sName, Len(sName) - 3)
        
        wk(6) = wk(6) & chr(13) & chr(9) & chr(9) & _
            "._" & Right(sName, Len(sName) - 3) & _
            " = " & sName & ".Text"
    Next i
    
    myCode = myCode & wk(0) & chr(13) & wk(1) & chr(13) & chr(13) & _
        "Private flgUpdate As Boolean" & chr(13) & chr(13) & _
        "Sub Show" & chr(13) & _
            chr(9) & "Initialize" & chr(13) & _
        "End Sub" & chr(13) & chr(13) & _
        "Sub Initialize" & chr(13) & _
            chr(9) & "With oDialog" & wk(2) & chr(13) & _
            chr(9) & "End With" & chr(13) & _
            wk(4) & chr(13) & _
            wk(3) & chr(13) & _
        "End Sub" & chr(13) & chr(13) & _
        "Sub setValues(obj As Object)" & chr(13) & _
            chr(9) & "With obj" & _
            wk(5) & chr(13) & _
            chr(9) & "End With" & chr(13) & _
        "End Sub" & chr(13) & chr(13) & _
        "Sub getValues" & chr(13) & _
            chr(9) & "With obj" & _
            wk(6) & chr(13) & _
            chr(9) & "End With" & chr(13) & _
        "End Sub"
    
    Show(myCode)
    
End Sub

まず、ダイアログに登録されている全コントロールとダイアログの名称を取得します。
そして、配列wkにそれぞれ

  1. コントロールの名称に合わせて変数を宣言するコード
  2. 表示用文字列を宣言するコード
  3. コントロールを変数に割り当てるコード
  4. 表示用文字列を初期化するコード
  5. コントロールに表示用文字列を割り当てるコード
  6. コントロール名からデータの構造を推測して、コントロール値をデータに割り当てるコード
  7. 同様に、データにコントロール値を割り当てるコード
を入力します。そして、取得したコードを見やすく整形してコードとして完成させます。
完成したコードを先ほど作成したShow関数で表示すると、内容をコピーし目的のモジュールに貼付けます。

ただし、LabelやScrollBarにListBox、CheckBoxなどの対応は全然考えていないのでこのままでは使えません。取得したコードは実情に合わせた手直しが必要になります。もちろん、凝ればもっといろいろ予め作るコードも生成できますがここではこれで終わりにします。是非、自分でカスタマイズしながら使って下さい。

ちなみに、chr(13)は改行、chr(9)はタブを意味します。これらの番号を調べるにはAsc関数を利用します。

試しにこれまでに作成したダイアログをこれで作ってみるなら、oDialogを初期化した後に以下のコードを追加してみて下さい。

mdlText.MakeDialogModuleTemplete(oDialog)

テーマ:OpenOffice.org - ジャンル:コンピュータ

担当編集ダイアログ その3

最後に、ボタン操作時の動作を作成します。Initialize関数中にて、btnOKへActionListenerを割り当てているので、これに対応した関数を作成すると共に、ActionListenerで示したように各コントロール用の処理としてbtnOK_actionPerformed関数も合わせて定義します。

まず、追加するコードを下記に示します。

mdlEditPerson

Private Sub btnOK_actionPerformed
    getValues
    flgUpdate = True
    oDialog.endExecute
End Sub

Private Sub dlgEditPersonActionListener_actionPerformed(oEvent)
    Select Case oEvent.Source.getModel().Name
        Case "btnOK"
            btnOK_actionPerformed
        Case Else
        
    End Select
End Sub

Private Sub dlgEditPersonActionListener_disposing: End Sub

各関数の説明をします。

  1. Sub btnOK_actionPerformed
    コントロールの値をデータに記録し、データが変更されたことを認識するためのフラグをTrueにしてからダイアログを閉じます。
  2. Sub dlgEditCategoryActionListener_actionPerformed(oEvent As ActionEvent)
    引数のActionEventオブジェクトから実行元のコントロール名を取得し、各コントロール毎の処理に振り分けます。ここでは、1つしかないので、奇異に感じられるかもしれませんが今度のダイアログと書式を合わせるためにあえて処理を分けてあります。
  3. Sub dlgEditCategoryActionListener_disposing
    ダイアログを終了時、ActionListenerを破棄するタイミングで実行される関数ですがこのダイアログでは必要ないので空白のままとます。但し、ActionListenerは必ずこの関数を実行しようとしますので、空白のままでも宣言しておかないとエラーになります。

以上で分類編集ダイアログの完成です。

このダイアログの動作確認をするために、仮のデータを1つ入力して以下のマクロを実行してみます。表示されたダイアログで値を変更し、設定後正しく変更内容が反映されているか確認してみて下さい。

mdlMain

Sub Test
    Initialize
    mdlPerson.LoadAll
    If mdlEditPerson.Show(1) Then mdlPerson.SaveAll
End Sub

テーマ:OpenOffice.org - ジャンル:コンピュータ

担当編集ダイアログ その2

編集対象の担当データをダイアログに割り当てたり、ダイアログに入力された情報をデータに反映させる関数を定義します。

まず、追加するコードを下記に示します。

mdlEditPerson

Sub setValues(obj As Object)
    With obj
        txtId.Text = ControlLabelString(obj._Id)
        txtName.Text = ._Name
        txtPhone1.Text = ._Phone1
        txtPhone2.Text = ._Phone2
        txtFAX.Text = ._FAX
        txtEMail.Text = ._EMail
        txtNote.Text = ._Note
    End With
End Sub
 
Sub getValues
    With Persons(Id)
        '._Id = txtId.Text
        ._Name = txtName.Text
        ._Phone1 = txtPhone1.Text
        ._Phone2 = txtPhone2.Text
        ._FAX = txtFAX.Text
        ._EMail = txtEMail.Text
        ._Note = txtNote.Text
    End With
End Sub

各関数の説明をします。

  1. Sub setValue(obj As Object)
    PersonTypeの変数を受け取ると、その値を各コントロールに配置していきます。
  2. Sub getValues
    Show関数で受け取ったIDのデータに各コントロールの値を代入していきます。

テーマ:OpenOffice.org - ジャンル:コンピュータ

担当編集ダイアログ その1

IDEにて「BASIC ダイアログ」を挿入し、名称を「dlgEditPerson」とします。そして、担当のデータ編集に必要なコントロールを配置すると下図のようになります。


次に、このダイアログを操作するためにモジュールを挿入し、名称を「mdlEditPerson」とします。
このモジュールでのダイアログの操作を簡便にするため、ダイアログと登録した全コントロール用の変数を宣言し、初期化処理にてそれを割り当てます。
また、ボタンを押した時の処理もマクロ内で割り当てるため、ActionLestener用変数も宣言します。

下記にコードの一部を示し、各部の説明を行います。

Option Explicit
 
Private oDialog As Object '---(1)
 
Private lblId As Object '---(2)
Private lblName As Object
Private lblPhone1 As Object
Private lblPhone2 As Object
Private lblFAX As Object
Private lblEMail As Object
Private lblNote As Object
Private txtId As Object
Private txtName As Object
Private txtPhone1 As Object
Private txtPhone2 As Object
Private txtFAX As Object
Private txtEMail As Object
Private btnOK As Object
Private txtNote As Object
 
Public dlgEditPerson_Title As String
Public dlgEditPerson_lblId_Text As String
Public dlgEditPerson_lblName_Text As String
Public dlgEditPerson_lblPhone1_Text As String
Public dlgEditPerson_lblPhone2_Text As String
Public dlgEditPerson_lblFAX_Text As String
Public dlgEditPerson_lblEMail_Text As String
Public dlgEditPerson_lblNote_Text As String
Public dlgEditPerson_btnOK_Label As String
 
Private oActionListener As Object '---(3)
 
Private Id As Integer '---(4)
Private flgUpdate As Boolean '---(5)
 
Sub Main
    
End Sub

Function Show(TargetId As Integer) As Boolean '---(6)
    
    Id = TargetId
    If Id < 1 Or mdlPerson.Count < Id Then Exit Function
    
    Initialize
    setValues(Persons(Id))
    flgUpdate = False
    
    With oDialog
        .execute
        .dispose
    End With
    
    Show = flgUpdate
    
End Function

Sub Initialize '---(7)
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgEditPerson)
    
    With oDialog
        .Title = dlgEditPerson_Title
        lblId = .getControl("lblId")
        lblName = .getControl("lblName")
        lblPhone1 = .getControl("lblPhone1")
        lblPhone2 = .getControl("lblPhone2")
        lblFAX = .getControl("lblFAX")
        lblEMail = .getControl("lblEMail")
        lblNote = .getControl("lblNote")
        txtId = .getControl("txtId")
        txtName = .getControl("txtName")
        txtPhone1 = .getControl("txtPhone1")
        txtPhone2 = .getControl("txtPhone2")
        txtFAX = .getControl("txtFAX")
        txtEMail = .getControl("txtEMail")
        btnOK = .getControl("btnOK")
        txtNote = .getControl("txtNote")
    End With
    
    oActionListener = CreateUnoListener("dlgEditPersonActionListener_", _
        "com.sun.star.awt.XActionListener") '---(8)
    
    btnOK.addActionListener(oActionListener)
    
    lblId.Text = dlgEditPerson_lblId_Text
    lblName.Text = dlgEditPerson_lblName_Text
    lblPhone1.Text = dlgEditPerson_lblPhone1_Text
    lblPhone2.Text = dlgEditPerson_lblPhone2_Text
    lblFAX.Text = dlgEditPerson_lblFAX_Text
    lblEMail.Text = dlgEditPerson_lblEMail_Text
    lblNote.Text = dlgEditPerson_lblNote_Text
    btnOK.Label = dlgEditPerson_btnOK_Label

End Sub

各部の解説を行います

  1. ダイアログおよび各コントロール用変数の宣言
  2. 表示初期化用変数の宣言
  3. アクションリスナー用変数の宣言
  4. 編集中のデータを認識するためのIDを保存する変数を宣言
  5. データの更新を行ったか否かを保存するための変数を宣言
  6. ダイアログ表示用の関数で、編集したい分類IDを引数とします
  7. ダイアログ初期化用関数
  8. 本ダイアログ用のアクションリスナー生成

次に、表示初期化用変数をmdlMain内のInitialize関数にて定義します。

mdlMainのInitialize関数に追記

    dlgEditPerson_Title = "担当編集"
    dlgEditPerson_lblId_Text = ControlLabelString("ID")
    dlgEditPerson_lblName_Text = ControlLabelString("氏名")
    dlgEditPerson_lblPhone1_Text = ControlLabelString("電話1")
    dlgEditPerson_lblPhone2_Text = ControlLabelString("電話2")
    dlgEditPerson_lblFAX_Text = ControlLabelString("FAX")
    dlgEditPerson_lblEMail_Text = ControlLabelString("E-Mail")
    dlgEditPerson_lblNote_Text = ControlLabelString("備考")
    dlgEditPerson_btnOK_Label = ControlLabelString("設定")

このまま実行すると、btnOKに設定したActionListener用の関数が正しく定義されいないので、エラーになります。もし、試しに動作させたい場合は、btnOK.addActionListener(oActionListener)をコメントアウトして見て下さい。

テーマ:OpenOffice.org - ジャンル:コンピュータ

Dbg_SupportedInterfaces - オブジェクトのインターフェースを調べる

残念ながら、僕はインターフェースについてうまく説明できるほどの言葉を持っていません。従って、とても抽象的な説明になることをご容赦下さい。

インターフェースを簡単に説明すると、オブジェクトはインターフェースとして持っているオブジェクトと同じ特性(主にプロパティやメソッドのこと)を持つことを意味します。例えば、画面の表示に関するクラスがあると、これは画面に表示されるオブジェクト全てに必要なものなので、ダイアログやコントロールなどにはそのクラスがインターフェースとして登録されています。
ただし、OOoBasicにある程度熟練してくればこのインターフェースについて知る事でより深いマクロを作成する事ができるのだと思いますが、Dbg_PropertiesやDbg_Methodsに比べて、直接的に利用できる情報とは言い難いものだと思います。

以下のコードを実行してみて下さい。

Sub Test
    Dim oDialog As Object
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgSample)
    MsgBox oDialog.Dbg_SupportedInterfaces
End Sub

すると、下記の情報が取得できます。

Supported interfaces by object 
"stardiv.Toolkit.UnoDialogControl":
    com.sun.star.container.XContainerListener
        com.sun.star.lang.XEventListener
    com.sun.star.awt.XTopWindow
    com.sun.star.awt.XDialog
    com.sun.star.util.XChangesListener
        com.sun.star.lang.XEventListener
    com.sun.star.lang.XTypeProvider
    com.sun.star.lang.XTypeProvider
    com.sun.star.awt.XUnoControlContainer
    com.sun.star.awt.XControlContainer
    com.sun.star.container.XContainer
    com.sun.star.awt.XControl
        com.sun.star.lang.XComponent
    com.sun.star.awt.XWindow
        com.sun.star.lang.XComponent
    com.sun.star.awt.XView
    com.sun.star.beans.XPropertiesChangeListener
        com.sun.star.lang.XEventListener
    com.sun.star.lang.XServiceInfo
    com.sun.star.accessibility.XAccessible
    com.sun.star.util.XModeChangeBroadcaster
    com.sun.star.lang.XTypeProvider
    com.sun.star.uno.XWeak
    com.sun.star.uno.XAggregation

ちなみに、ガントチャートforOOoの開発ではこの情報を用いて何か有用な結果を導くという事はありませんでした。僕もこの情報を使って有用なプログラミングができるほどの実力を早く身につけたいものです。

テーマ:OpenOffice.org - ジャンル:コンピュータ

Dbg_Methods - オブジェクトのメソッドを調べる

Dbg_Propertiesと同様にオブジェクトの取得ができれば、「Dbg_Methods」でメソッドを調べる事もできます。

Dbg_Propertiesと同様にダイアログのメソッドを調べてみます。下記のコードを実行してみて下さい。

Sub Test
    Dim oDialog As Object
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgSample)
    MsgBox oDialog.Dbg_Methods
End Sub

結果は下記のようになります。

Methods of object 
"stardiv.Toolkit.UnoDialogControl":
SbxEMPTY queryInterface ( SbxOBJECT ) ;
SbxVOID disposing ( SbxOBJECT ) ;
SbxVOID elementInserted ( SbxOBJECT ) ;
SbxVOID elementRemoved ( SbxOBJECT ) ;
SbxVOID elementReplaced ( SbxOBJECT ) ;
SbxVOID addTopWindowListener ( SbxOBJECT ) ;
SbxVOID removeTopWindowListener ( SbxOBJECT ) ;
SbxVOID toFront ( void ) ;
SbxVOID toBack ( void ) ;
SbxVOID setMenuBar ( SbxOBJECT ) ;
SbxVOID setTitle ( SbxSTRING ) ;
SbxSTRING getTitle ( void ) ;
SbxINTEGER execute ( void ) ;
SbxVOID endExecute ( void ) ;
SbxVOID changesOccurred ( SbxOBJECT ) ;
SbxARRAY getTypes ( void ) ;
SbxARRAY getImplementationId ( void ) ;
SbxVOID setTabControllers ( SbxARRAY ) ;
SbxARRAY getTabControllers ( void ) ;
SbxVOID addTabController ( SbxOBJECT ) ;
SbxVOID removeTabController ( SbxOBJECT ) ;
SbxVOID setStatusText ( SbxSTRING ) ;
SbxARRAY getControls ( void ) ;
SbxOBJECT getControl ( SbxSTRING ) ;
SbxVOID addControl ( SbxSTRING, SbxOBJECT ) ;
SbxVOID removeControl ( SbxOBJECT ) ;
SbxVOID addContainerListener ( SbxOBJECT ) ;
SbxVOID removeContainerListener ( SbxOBJECT ) ;
SbxVOID dispose ( void ) ;
SbxVOID addEventListener ( SbxOBJECT ) ;
SbxVOID removeEventListener ( SbxOBJECT ) ;
SbxVOID setContext ( SbxOBJECT ) ;
SbxOBJECT getContext ( void ) ;
SbxVOID createPeer ( SbxOBJECT, SbxOBJECT ) ;
SbxOBJECT getPeer ( void ) ;
SbxBOOL setModel ( SbxOBJECT ) ;
SbxOBJECT getModel ( void ) ;
SbxOBJECT getView ( void ) ;
SbxVOID setDesignMode ( SbxBOOL ) ;
SbxBOOL isDesignMode ( void ) ;
SbxBOOL isTransparent ( void ) ;
SbxVOID setPosSize ( SbxLONG, SbxLONG, SbxLONG, SbxLONG, SbxINTEGER ) ;
SbxOBJECT getPosSize ( void ) ;
SbxVOID setVisible ( SbxBOOL ) ;
SbxVOID setEnable ( SbxBOOL ) ;
SbxVOID setFocus ( void ) ;
SbxVOID addWindowListener ( SbxOBJECT ) ;
SbxVOID removeWindowListener ( SbxOBJECT ) ;
SbxVOID addFocusListener ( SbxOBJECT ) ;
SbxVOID removeFocusListener ( SbxOBJECT ) ;
SbxVOID addKeyListener ( SbxOBJECT ) ;
SbxVOID removeKeyListener ( SbxOBJECT ) ;
SbxVOID addMouseListener ( SbxOBJECT ) ;
SbxVOID removeMouseListener ( SbxOBJECT ) ;
SbxVOID addMouseMotionListener ( SbxOBJECT ) ;
SbxVOID removeMouseMotionListener ( SbxOBJECT ) ;
SbxVOID addPaintListener ( SbxOBJECT ) ;
SbxVOID removePaintListener ( SbxOBJECT ) ;
SbxBOOL setGraphics ( SbxOBJECT ) ;
SbxOBJECT getGraphics ( void ) ;
SbxOBJECT getSize ( void ) ;
SbxVOID draw ( SbxLONG, SbxLONG ) ;
SbxVOID setZoom ( SbxSINGLE, SbxSINGLE ) ;
SbxVOID propertiesChange ( SbxARRAY ) ;
SbxSTRING getImplementationName ( void ) ;
SbxBOOL supportsService ( SbxSTRING ) ;
SbxARRAY getSupportedServiceNames ( void ) ;
SbxOBJECT getAccessibleContext ( void ) ;
SbxVOID addModeChangeListener ( SbxOBJECT ) ;
SbxVOID removeModeChangeListener ( SbxOBJECT ) ;
SbxVOID addModeChangeApproveListener ( SbxOBJECT ) ;
SbxVOID removeModeChangeApproveListener ( SbxOBJECT ) ;
SbxOBJECT queryAdapter ( void ) ;
SbxVOID setDelegator ( SbxOBJECT ) ;
SbxEMPTY queryAggregation ( SbxOBJECT )

出力される文字列は改行がきちんとされていないので、Dbg_Propertiesの結果より読みづらいですが読んで読めない事も無い。また、「;」が区切り文字になっているので、これを改行に変換すればより見やすくなります。

この中を精査してみると、表示や表示に関わる情報の取得、リスナーの登録など様々なメソッドが用意されているのがわかります。ここで、型名が「SbxVOID」となっているものは戻り値がないことを意味します。

また、Dbg_Methodsはリスナーを調べる際にとても有効で、リスナーの持っている動作の一覧を取得する事ができます。

アクションリスナーを調べると、

Methods of object 
"com.sun.star.awt.XActionListener":
SbxEMPTY queryInterface ( SbxOBJECT ) ; 
SbxVOID disposing ( SbxOBJECT ) ; 
SbxVOID actionPerformed ( SbxOBJECT )
となり、disposingとacttionPerformedの2つがあることがわかります。
次にマウスリスナーを調べてみると、
Methods of object 
"com.sun.star.awt.XMouseListener":
SbxEMPTY queryInterface ( SbxOBJECT ) ; 
SbxVOID disposing ( SbxOBJECT ) ; 
SbxVOID mousePressed ( SbxOBJECT ) ; 
SbxVOID mouseReleased ( SbxOBJECT ) ; 
SbxVOID mouseEntered ( SbxOBJECT ) ; 
SbxVOID mouseExited ( SbxOBJECT ) 
となり、disposing、mousePressed(ボタンを押した時)、mouseReleased(ボタンを放した時)、mouseEntered(カーソルがオブジェクトの上に来た時)、mouseExited(カーソルがオブジェクトの上から外れた時)の5つがあることがわかります。
これがわかれば、リスナーを使用する場合にも予め必要な関数を宣言しておくことができますので、よけいなエラーに煩わされることが少なくなるのではないでしょうか。

テーマ:OpenOffice.org - ジャンル:コンピュータ

OpenOffice.orgを使うメリットとデメリット

色々なところで議論されていることですが、仕事で使おうとするとデメリットばかりが目につきますね。

自作のPCや安価なPCでなければほとんどExcelとWordは入っていて、家でもExcelやWordを使っている人は多くいますし、デザイン系の仕事をしている人や研究者が好んで使うMacにもExcelとWord、PowerPointがあることからMSOfficeで作成したファイルは、まずどこへ行っても見る事ができます。
このことから、仕事で受け渡しされるファイルの多くはMSOfficeで作成されたもので、次に多いのはPDFではないでしょうか。一太郎で作られたものも極端に減ってきましたし、ましてやOpenOffice.orgのファイルが送られてきたことなどは一度もありません。

もしOpenOffice.orgで作ったファイルを送ったら迷惑をかけるだけだし、相手によっては怒りかねません。

しかし、こんな状況になったのはこの10年くらいのことです。僕がVBAで開発を始めた頃は、表計算はLotas1-2-3、ワープロは一太郎というのが業界標準でした。これが逆転した現象について、MSの販売手法を指摘する人もいるかもしれませんが、MSOfficeが優位に立てたのはVBAという開発環境もその一因だと思います。
僕はOffice4.2を手に入れた時、ソフトに付属の極めて分厚いマクロの取扱説明書に目を通した後、これを開発プラットフォームにしようと決めました。単独のアプリケーションを作成できる開発環境には自由度で負けますが、業務に必要なインターフェースを予め備えている開発環境というのはとても魅力的だと感じたことを今でも覚えています。
Office97が出る頃には書店に多くの書籍が並ぶようになり、同時にインターネットの普及も進んだことからVBAを扱ったホームページもたくさん出てきて、これがExcelを代表とするMSOfficeの普及を後押ししたのだと考えています。

では、OpenOffice.orgはどうでしょうか。

市場にはMSOfficeという圧倒的シェアを誇るソフトがあり、このソフトに関する書籍はほとんど無いという状況はまさに10年前のExcel/Wordと酷似しています。
そして、OpenOffice.orgにはMSOfficeより優れた開発環境があります。MSOfficeはほとんどのPCにインストールされているとは言え、Personal版ではExcelとWordしかありません。これに対し、OpenOffice.orgには2.0からBaseというデータベースアプリケーションがついています。あまりデータベースは一般的でないという意見もあるかもしれませんが、開発者ならデータベースがあれば使う人がほとんどだと思います。
MSOfficeでデータベースを使って開発をしようと考えたとき、Accessが入っているか他のデータベースアプリケーションがないと多少面倒です。これに対し、OpenOffice.org2.0以降であれば、Baseを使ってデータベースを自由に操作できるのです。
また、サーバー用途でLinuxが広がりつつある現状もOpenOffice.orgにとっては好材料だと言えます。邪道かもしれませんが、開発環境に簡単な文書作成環境が入っているのはとても便利です。また、サーバーサイドでMSOfficeのファイルを生成するのは多少手間とお金がかかりますが、OpenOffice.orgのファイルなら無料で簡単に生成できます。

一般的にOpenOffice.orgのメリットは無料であることだと言われています。しかし、僕はそれよりも多くの環境で動作する事の方がメリットだと考えています。そしてこのマルチプラットフォームの環境に早い段階で移行しておくと、今後の市場動向に柔軟な対応が可能になり、分野によってはとても優位な立場になれるのではないでしょうか。

そして、オープンドキュメント形式を扱う各種ライブラリが出揃い、OpenOffice.orgのマクロに関する書籍も店頭に多く並ぶようになれば、OpenOffice.orgのマクロを作る人も増えていることでしょう。もし、そうなれば必ずMSOfficeが優位を保っているとは言えないのではないでしょうか。
もしくは別のオフィススイートが台頭してきているかもしれません。いずれにせよ、多くのアプリケーションで、作成したアプリケーションを気にせずにファイルの編集ができるようになるでしょう。

このブログは、こんな未来を築くきっかけの一つになることを目指しています。

テーマ:OpenOffice.org - ジャンル:コンピュータ

Dbg_Properties - オブジェクトのプロパティを調べる

OOoBasicでマクロを作成する場合に、一番の問題として言えるのは「情報の少なさ」です。
やりたいことがあっても、どのようにしてその問題を解決すればいいのかわからないのでは、実現できるはずがありません。

ただ、操作対象のオブジェクトを取得する方法がわかっていれば、そこに光明はあります。
ここで、とても役に立つのが「Dbg_Properties」です。

例えば、ダイアログの持つプロパティを確認するには、以下のようなコードを書いてみます。ここで、以前作成したdlgSampleを使用します。

Sub Test
    Dim oDialog As Object
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgSample)
    MsgBox oDialog.Dbg_Properties
End Sub

これを実行すると、下記のメッセージが表示されます。

Properties of object 
"stardiv.Toolkit.UnoDialogControl":
SbxOBJECT MenuBar; 
SbxSTRING Title; 
SbxARRAY Types; 
SbxARRAY ImplementationId; 
SbxARRAY TabControllers; 
SbxARRAY Controls; 
SbxSTRING StatusText; 
SbxOBJECT Context; 
SbxOBJECT Peer; 
SbxOBJECT Model; 
SbxOBJECT View; 
SbxBOOL DesignMode; 
SbxOBJECT PosSize; 
SbxBOOL Visible; 
SbxBOOL Enable; 
SbxOBJECT Graphics; 
SbxOBJECT Size; 
SbxSTRING ImplementationName; 
SbxARRAY SupportedServiceNames; 
SbxOBJECT AccessibleContext; 
SbxOBJECT Delegator; 
SbxSTRING Dbg_SupportedInterfaces; 
SbxSTRING Dbg_Properties; 
SbxSTRING Dbg_Methods

これを見ると、「Sbx~」に型名が続き、空白を置いてプロパティ名が一覧できることがわかります。基礎的な英語とプログラミングの知識があれば、この一覧だけでダイアログの情報を取得または設定するために必要なプロパティをほとんど把握できると思います。
また、型名が「SbxOBJECT」となっているものは、それを取得して「Dbg_Properties」を表示する事で、そのオブジェクトの持つプロパティを知る事ができるのです。

試しに、Modelプロパティについて調べてみます。先ほどのコードを多少改造して

MsgBox oDialog.Model.Dbg_Properties
としてみると、結果は下記のようになります。

Properties of object 
"stardiv.Toolkit.UnoControlDialogModel":
SbxLONG/void BackgroundColor; SbxBOOL Closeable; 
SbxSTRING DefaultControl; SbxBOOL Enabled; 
SbxSINGLE FontCharWidth; SbxINTEGER FontCharset; 
SbxOBJECT FontDescriptor; SbxINTEGER FontEmphasisMark; 
SbxINTEGER FontFamily; SbxSINGLE FontHeight; 
SbxBOOL FontKerning; SbxSTRING FontName; 
SbxSINGLE FontOrientation; SbxINTEGER FontPitch; 
SbxINTEGER FontRelief; SbxINTEGER FontSlant; 
SbxINTEGER FontStrikeout; SbxSTRING FontStyleName; 
SbxINTEGER FontType; SbxINTEGER FontUnderline; 
SbxSINGLE FontWeight; SbxINTEGER FontWidth; 
SbxBOOL FontWordLineMode; SbxLONG Height; 
SbxSTRING HelpText; SbxSTRING HelpURL; 
SbxBOOL Moveable; SbxSTRING Name; 
SbxLONG PositionX; SbxLONG PositionY; 
SbxBOOL Sizeable; SbxLONG Step; 
SbxINTEGER TabIndex; SbxSTRING Tag; 
SbxLONG/void TextColor; SbxLONG/void TextLineColor; 
SbxSTRING Title; SbxLONG Width; 
SbxOBJECT PropertySetInfo; SbxSTRING PropertyToDefault; 
SbxOBJECT Events; SbxARRAY Types; 
SbxARRAY ImplementationId; SbxOBJECT Delegator; 
SbxARRAY AvailableServiceNames; SbxOBJECT ElementType; 
SbxARRAY ElementNames; SbxBOOL GroupControl; 
SbxARRAY ControlModels; SbxLONG GroupCount; 
SbxSTRING ServiceName; SbxSTRING ImplementationName; 
SbxARRAY SupportedServiceNames; SbxSTRING Dbg_SupportedInterfaces; 
SbxSTRING Dbg_Properties; SbxSTRING Dbg_Methods

すると、中にフォントや大きさ、色など表示に関する様々なプロパティがあることがわかります。
このような情報は開発者の方々が作成されたオブジェクトについて、それぞれに記載するようなルールになっているようです。ほぼ全てのオブジェクトがこのような情報を持っているので、どうしても見つからない情報があってもこの機能を活用していくことで目的を達成できる可能性が高くなるのではないでしょうか。

テーマ:OpenOffice.org - ジャンル:コンピュータ

分類編集ダイアログ その3

最後に、ボタン操作時の動作を作成します。Initialize関数中にて、btnOKへActionListenerを割り当てているので、これに対応した関数を作成すると共に、ActionListenerで示したように各コントロール用の処理としてbtnOK_actionPerformed関数も合わせて定義します。

まず、追加するコードを下記に示します。

mdlEditCategory

Private Sub btnOK_actionPerformed
    getValues
    flgUpdate = True
    oDialog.endExecute
End Sub
 
Private Sub dlgEditCategoryActionListener_actionPerformed(oEvent)
    Select Case oEvent.Source.getModel().Name
        Case "btnOK"
            btnOK_actionPerformed
        Case Else
        
    End Select
End Sub
 
Private Sub dlgEditCategoryActionListener_disposing

End Sub

各関数の説明をします。

  1. Sub btnOK_actionPerformed
    コントロールの値をデータに記録し、データが変更されたことを認識するためのフラグをTrueにしてからダイアログを閉じます。
  2. Sub dlgEditCategoryActionListener_actionPerformed(oEvent As ActionEvent)
    引数のActionEventオブジェクトから実行元のコントロール名を取得し、各コントロール毎の処理に振り分けます。ここでは、1つしかないので、奇異に感じられるかもしれませんが今後作成するダイアログと書式を合わせるためにあえて処理を分けてあります。
  3. Sub dlgEditCategoryActionListener_disposing
    ダイアログを終了時、ActionListenerを破棄するタイミングで実行される関数ですがこのダイアログでは必要ないので空白のままとます。但し、ActionListenerは必ずこの関数を実行しようとしますので、空白のままでも宣言しておかないとエラーになります。

以上で分類編集ダイアログの完成です。

このダイアログの動作確認をするために、仮のデータを1つ入力して以下のマクロを実行してみます。表示されたダイアログで値を変更し、設定後正しく変更内容が反映されているか確認してみて下さい。

mdlMain

Sub Test
    Initialize
    mdlCategory.LoadAll
    If mdlEditCategory.Show(1) Then mdlCategory.SaveAll
End Sub

テーマ:OpenOffice.org - ジャンル:コンピュータ

分類編集ダイアログ その2

編集対象の分類データをダイアログに割り当てたり、ダイアログに入力された情報をデータに反映させる関数を定義します。

まず、追加するコードを下記に示します。

mdlEditCategory

Private Sub setValues(obj As Object)
    
    txtId.Text = ControlLabelString(obj._Id)
    txtName.Text = obj._Name
    chkVisible.State = Bool2State(obj._Visible)
    
End Sub
 
Private Sub getValues
    
    With Categories(Id)
        '._Id = txtId.Text
        ._Name = txtName.Text
        ._Visible = State2Bool(chkVisible)
    End With
    
End Sub

各関数の説明をします。

  1. Sub setValue(obj As Object)
    CategoryTypeの変数を受け取ると、その値を各コントロールに配置していきます。
  2. Sub getValues
    Show関数で受け取ったIDの分類データに各コントロールの値を代入していきます。

ここで、Boot2State関数とState2Bool関数を使用していますが、これは

mdlMain

Public Function State2Bool(chk As Object) As Boolean
    If chk.State = 1 Then :State2Bool = True
    Else :State2Bool = False
    End If
End Function
 
Public Function Bool2State(val As Boolean) As Integer
    If val Then :Bool2State = 1
    Else :Bool2State = 0
    End If
End Function
とmdlMainに定義しておきます。

VBAではチェックボックスの状態を取得するとき、CheckBox1.ValueとするとBoolean型の値を受け取ることができますが、OOoBasicではCheckBox1.StateとするとInteger型の値を戻します。そして、チェックされていれば1、されていなければ0が帰ってきますので、その条件を判断しBoolean型に変換しているのがState2Bool関数です。
また値を設定する場合に、同様にBoolean型をStateプロパティに合うよう変換するための関数がBool2State関数です。

テーマ:OpenOffice.org - ジャンル:コンピュータ

分類編集ダイアログ その1

IDEにて「BASIC ダイアログ」を挿入し、名称を「dlgEditCategory」とします。そして、分類のデータ編集に必要なコントロールを配置すると下図のようになります。

次に、このダイアログを操作するためにモジュールを挿入し、名称を「mdlEditCategory」とします。
このモジュールでダイアログの操作をするため、ダイアログと登録した全コントロール用の変数を宣言し、初期化処理にてそれを割り当てます。
また、ボタンを押した時の処理もマクロ内で割り当てるため、ActionLestener用変数も宣言します。

下記にコードの一部を示し、各部の説明を行います。

Option Explicit
 
Private oDialog As Object '---(1)
 
Private lblId As Object
Private lblName As Object
Private txtId As Object
Private txtName As Object
Private chkVisible As Object
Private btnOK As Object
 
Public dlgEditCategory_Title As String '---(2)
Public dlgEditCategory_lblId_Text As String
Public dlgEditCategory_lblName_Text As String
Public dlgEditCategory_chkVisible_Label As String
Public dlgEditCategory_btnOK_Label As String
 
Private oActionListener As Object '---(3)
 
Private Id As Integer '---(4)
Private flgUpdate As Boolean '---(5)
 
Sub Main
    mdlMain.Initialize
    LoadCategories
    Show(1)
End Sub
 
Public Function Show(TargetId As Integer) As Boolean '---(6)
    
    flgUpdate = False
    
    Id = TargetId
    If Id < 1 Or mdlCategory.Count < Id Then Exit Function
    
    oDialog = _
        createUnoDialog(DialogLibraries.Standard.dlgEditCategory) '---(7)
    Initialize
    setValues(Categories(Id)) '---次回作解説します
    With oDialog
        .execute
        .dispose
    End With
    
    Show = flgUpdate
    
End Function
 
Private Sub Initialize '---(8)
    
    With oDialog
        .Title = dlgEditCategory_Title
        lblId = .getControl("lblId")
        lblName = .getControl("lblName")
        txtId = .getControl("txtId")
        txtName = .getControl("txtName")
        chkVisible = .getControl("chkVisible")
        btnOK = .getControl("btnOK")
    End With
    
    oActionListener = CreateUnoListener( _
        "dlgEditCategoryActionListener_", _
        "com.sun.star.awt.XActionListener") '---(9)
    
    lblId.Text = dlgEditCategory_lblId_Text '---(10)
    lblName.Text = dlgEditCategory_lblName_Text
    chkVisible.Label = dlgEditCategory_chkVisible_Label
    btnOK.setLabel(dlgEditCategory_btnOK_Label)
    btnOK.addActionListener(oActionListener)
    
End Sub

各部の解説を行います

  1. ダイアログおよび各コントロール用変数の宣言
  2. 表示初期化用変数の宣言
  3. アクションリスナー用変数の宣言
  4. 編集中のデータを認識するためのIDを保存する変数を宣言
  5. データの更新を行ったか否かを保存するための変数を宣言
  6. ダイアログ表示用の関数で、編集したい分類IDを引数とします
  7. ダイアログの生成
  8. ダイアログ初期化用関数
  9. 本ダイアログ用のアクションリスナー生成
  10. コントロール変数にそれぞれの設定を割り当てます

次に、表示初期化用変数をmdlMain内のInitialize関数にて定義します。

mdlMainのInitialize関数に追記

    dlgEditCategory_Title = "分類編集"
    dlgEditCategory_lblId_Text = ControlLabelString("ID")
    dlgEditCategory_lblName_Text = ControlLabelString("名称")
    dlgEditCategory_chkVisible_Label = ControlLabelString("表示")
    dlgEditCategory_btnOK_Label = ControlLabelString("設定")

ここで、使用しているControlLabelString関数はアクセスキーを表示しないためのもので、

Function ControlLabelString(Label As String) As String
    ControlLabelString = Label & "~" & chr(13)
End Function
とし、mdlMainに追記しておきます。

このまま実行すると、btnOKに設定したActionListener用の関数が正しく定義されいないので、エラーになります。もし、試しに動作させたい場合は、btnOK.addActionListener(oActionListener)をコメントアウトしてみて下さい。

テーマ:OpenOffice.org - ジャンル:コンピュータ

リストボックスの利用

今度はリストボックスを配置します。

リストボックスの名前を「lstInput」として、OKボタンを押すとテキストボックスにされた内容をリストに追加し、テキストボックスの内容をクリアするという処理を作成します。また、「btnClear」という名前のボタンをもう一つ追加して、リストボックスを初期化させるようにします。
各コントロールを配置したダイアログは下図のようになります。


次に、コードを以下に示します。

Private oDialog As Object
 
Private btnOK As Object '---(1)
Private btnCancel As Object
Private txtInput As Object
Private lstInput As Object
 
Private oActionListener As Object
 
Sub Show
    
    Initialize
    
    With oDialog
        .execute
        .dispose
    End With
    
End Sub
 
Sub Initialize
    
    oDialog =  createUnoDialog(DialogLibraries.Standard.dlgSample)
    
    oActionListener = CreateUnoListener("dlgSampleActionListener_", _
        "com.sun.star.awt.XActionListener")
    
    btnOK = oDialog.getControl("btnOK") '---(2)
    btnOK.addActionListener(oActionListener)
    btnOK.Label = "~Set"
    
    btnCancel = oDialog.getControl("btnCancel")
    btnCancel.addActionListener(oActionListener)
    btnCancel.Label = "~Clear"
    
    txtInput = oDialog.getControl("txtInput")
    txtInput.Text = ""
    
    lstInput = oDialog.getControl("lstInput")
    
End Sub
 
Sub btnOK_Click '---(3)
    If txtInput.Text = "" Then Exit Sub
    lstInput.addItem(txtInput.Text, 0)
    txtInput.Text = ""
End Sub
 
Sub btnCancel_Click '---(4)
    
    lstInput.removeItems(0, lstInput.getItemCount)
    
End Sub
 
Sub dlgSampleActionListener_actionPerformed(oEvent)
    
    Select Case oEvent.Source.getModel.Name '---(5)
        Case "btnOK"
            btnOK_Click
        Case "btnCancel"
            btnCancel_Click
    End Select
End Sub
 
Sub dlgSampleActionListener_disposing

End Sub

内容を解説します

  1. 全コントロール用の変数を宣言
  2. ボタンコントロールにアクションリスナーを登録し、ラベルを合わせます。また、他のコントロールも同様に変数に割り当てます
  3. btnOKをクリックした時、txtInputが空白ならば終了し、そうでない場合はリストボックスに登録します
  4. btnCancelをクリックしたらリストボックスの内容を消去します
  5. アクションリスナーの関数を呼び出す時、引数を付けると呼び出し元のオブジェクトを取得できます。そこで、呼び出し元のオブジェクトから名称を選択し、それぞれの名称に合わせて処理を分岐します

リストボックスは便利なので、是非利用したいものです。ついでに、選択された項目番号を取得する方法は

lstInput.getSelectedItemPos
です。腕試しに、lstInputへアクションリスナーを登録してリストボックスをダブルクリックすると選択された項目をMsgBox関数で表示するマクロを作ってみて下さい。

テーマ:OpenOffice.org - ジャンル:コンピュータ

テキストボックスの利用

今度はテキストボックスを配置します。

テキストボックスの名前を「txtInput」として、OKボタンを押すと入力された内容をメッセージボックスに表示してから内容をクリアするという処理を作成します。
テキストボックスとボタンを配置したダイアログは下図のようになります。


次に、コードを以下に示します。

Private oDialog As Object
Private btnOK As Object
Private txtInput As Object '---(1)
 
Private oActionListener As Object
 
Sub Show
    
    Initialize
    
    With oDialog
        .execute
        .dispose
    End With
    
End Sub
 
Sub Initialize
    
    oDialog =  createUnoDialog(DialogLibraries.Standard.dlgSample)
    
    oActionListener = CreateUnoListener("dlgSampleActionListener_", _
        "com.sun.star.awt.XActionListener")
    
    btnOK = oDialog.getControl("btnOK")
    btnOK.addActionListener(oActionListener)
    btnOK.Label = "~OK"
    
    txtInput = oDialog.getControl("txtInput") '---(2)
    txtInput.Text = "" '---(3)
    
End Sub
 
Sub btnOK_Click
    'oDialog.endExecute
    MsgBox txtInput.Text '---(4)
    txtInput.Text = ""
End Sub
 
Sub dlgSampleActionListener_actionPerformed
    btnOK_Click
End Sub
 
Sub dlgSampleActionListener_disposing
 
End Sub

内容を解説します

  1. ボタン同様にテキストボックス用変数を宣言します
  2. ダイアログ中のテキストボックスを変数に割り当てます
  3. 初期処理としてテキストボックスの内容を消去します
  4. ボタンをクリックしたらMsgBox関数でテキストボックスの内容を表示し、内容を消去します

これもまたボタンと同じで

MsgBox oDialog.getControl("txtInput").Text
oDialog.getControl("txtInput").Text = ""
というように毎回記述しても構いません。

テーマ:OpenOffice.org - ジャンル:コンピュータ

データ交換、コピー「担当」

読込んだデータを交換したりコピーする関数を定義します。

これまでと同様に「mdlPerson」に追記していきます。

mdlPerson
Public Sub Swap(Data1 As PersonType, Data2 As PersonType) '---(1)
    
    Dim wk As PersonType
    
    Copy(Data1, wk)
    Copy(Data2, Data1)
    Copy(wk, Data2)
    
End Sub

Public Sub Copy(Src As PersonType, Dst As PersonType) '---(2)
    
    With Src
        'Dst._Id = ._Id
        Dst._Name = ._Name
        Dst._Phone1 = ._Phone1
        Dst._Phone2 = ._Phone2
        Dst._FAX = ._FAX
        Dst._EMail = ._EMail
        Dst._Note = ._Note
    End With
    
End Sub

内容について説明します。

  1. 後に作るコピー用関数を使って、データ交換処理を行います。
  2. コピー用関数を定義します。

テーマ:OpenOffice.org - ジャンル:コンピュータ

addActionListener - 自作ダイアログのボタンに処理を登録する

前回配置したボタン「btnOK」をクリックするとダイアログを閉じるマクロを作ってみます。

ここで、必要になってくるのがActionListenerです。直訳すると「動作の聞き手」と言った感じでしょうか。何かのアクションを耳を澄まして待ち構えていて、アクションを聞きつけると動作を行うものという説明でわかるでしょうか。

VBAではこのようなものを利用しなくても、「btnOK_Click()」という関数が半自動的に生成されるのでこの中に処理を書けばいいのですが、OOoBasicでは多少面倒です。IDEのダイアログ編集画面で、プロパティからクリック時にマクロを割り当てる事も出来ますが、せっかくダイアログ用にモジュールを作るのだから、この辺りもコードで処理するようにしてみたいと思います。
まず、コードを下記に示します。

mdlSample

Private oDialog As Object
Private btnOK As Object
 
Private oActionListener As Object '---(1)
 
Sub Show
    
    Initialize
    
    btnOK.Label = "~OK"
    
    With oDialog
        .execute
        .dispose
    End With
    
End Sub
 
Sub Initialize
    
    oDialog =  createUnoDialog(DialogLibraries.Standard.dlgSample)
    
    oActionListener = CreateUnoListener("dlgSampleActionListener_", _
        "com.sun.star.awt.XActionListener") '---(2)
    
    btnOK = oDialog.getControl("btnOK")
    btnOK.addActionListener(oActionListener)
    
End Sub
 
Sub btnOK_Click '---(3)
    oDialog.endExecute
End Sub

Sub dlgSampleActionListener_actionPerformed '---(4)
    btnOK_Click
End Sub
 
Sub dlgSampleActionListener_disposing
 
End Sub

コードの説明をすると、

  1. アクションリスナー用の変数を用意します。
  2. 初期化処理にてアクションリスナーを生成し、btnOKにアクションリスナーを登録します。リスナーの生成方法にて、前側の引数はリスナーの名前で「○○_」というように"_"で終わる文字列を指定します。後側は生成するリスナーの種類ですが、アクションリスナー以外にもいくつか種類があり、これは後述したいと思います。
  3. VBAライクにbtnOK_Click関数を定義し、ダイアログを閉じる命令を書きます。そして、これをアクションリスナー用関数から呼び出すようにします。
  4. アクションリスナーの名前に合わせて関数を作ります。アクションリスナーには「actionPerformed」と「disposing」の2つがあるので、生成時に付けた名称と組み合わせて、「dlbSampleActionListener_actionPerformed」と「dlgSampleActionListener_disposing」の2つの関数を定義します。

ここで、Module1のMainを実行するとダイアログが表示され、ボタンをクリックするとダイアログが閉じます。

なぜアクションリスナー関数内で、ボタンをクリックした処理を直接書かないのかという疑問を感じるかもしれませんが、これは僕なりの工夫です。コントロールを多く配置したとき、同じ数だけのアクションリスナーを定義してもいいのですが、これは多少不便です。そこで、一つのアクションリスナーを全コントロールに登録し、アクションリスナー側でどのコントロールから呼ばれたかを判断して処理を分岐させるようにしています。こうすることで、VBAライクなコントロール用の関数を定義する事ができるので、アクションリスナーをラッパーみたいに使うのが良いと考えているためです。

これもまた賛否両論あると思いますが、色々試してみて自分がやりやすいスタイルを確立してみて下さい。

テーマ:OpenOffice.org - ジャンル:コンピュータ

getControl - 自作ダイアログにボタンを配置する

自作ダイアログの利用で作成したダイアログにボタンを配置してみます。

IDEでダイアログ編集画面を表示し、「コントロール」アイコンをクリックします。すると、コントロールの一覧が表示されるので、コマンドボタンアイコンをクリックして、ダイアログ上に配置するとボタンが追加されます。
ここで、このボタンをダブルクリックするとプロパティを編集できるようになるので、名前を「btnOK」とします。

完成したダイアログは下図となります。


自作ダイアログの利用で説明したようにコードは「mdlSample」に書きますが、多少改造してみます。

mdlSample
Private oDialog As Object
Private btnOK As Object
 
Sub Show
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgSample)
    Initialize
    
    btnOK.Label = "OK"
    
    With oDialog
        .execute
        .dispose
    End With
    
End Sub
 
Sub Initialize
    btnOK = oDialog.getControl("btnOK")
End Sub

内容を説明します。
まず、ダイアログとボタン用の変数を関数の外で宣言する事で、モジュール内の全関数で使用できるグローバル変数とします。
Initialize関数を作成し、ダイアログの設定を行うコードをこちらに集約します。今回は「btnOK」というコントロールを「btnOK」という変数に割り当てる処理を書きました。こうする事で、VBAと同じようにモジュール内でボタンへのアクセスが容易になります。
Show関数にInitialize関数を追加し、ボタンへのアクセスが容易になったことを示す例として、ボタンの表示名を変更する命令を追加してみました。

Module1にて、mdlSample.Showというコードを実行するとダイアログが表示され、ボタンの表示名が「OK」に変わっているのがわかります。

ちなみにVBAでボタンの名称を変更するコードは

btnOK.Caption = "OK"
となります。似てませんか?通常のOOoBasicコードで同様の事をする場合は
oDialog.getControl("btnOK").Label = "OK"
となりますが、これから多くのコントロールを配置していく時に多少不便を感じると思います。人それぞれ好みもあるだろうから、前述の手法が必ず正しいとは言いませんが、VBAに慣れ親しんだ人には見やすいのではないかと思います。

また、表示した時のボタン表示名が「OK(A)」となっていると思います。これはAlt + Aでこのボタンにアクセスできるようになっている事を示しますが、意図しないもので気に入らない人もいるでしょう。これを「OK」としたい、もしくは「OK」としたい場合は下記のようにします

REM Alt+Oでアクセスしたい場合
btnOK.Label = "~OK"
REM OKのみの場合
btnOK.Label = "OK" & "~" & chr(13)

テーマ:OpenOffice.org - ジャンル:コンピュータ

データ書込み「担当」

読込みと同様に、「mdlPerson」に追記します。

mdlPerson
Public Function SaveAll() As Integer '---(1)
    
    Dim i As Integer
    
    For i = 1 To UBound(Persons()) '---(2)
        If Not SaveById(Persons(i)) Then Exit For '---(3)
    Next i
    Cells(PersonSheet, 1, i + 1).String = "" '---(4)
    
    SaveAll = i - 1
    
End Function
 
Public Function SaveById(Person As PersonType) As Boolean
    
    Dim i As Integer
    Dim Id As Integer
    
    i = 1
    With Person
        Id = ._Id + 1
        Cells(PersonSheet, i, Id).Value = ._Id : i = i + 1
        Cells(PersonSheet, i, Id).String = ._Name : i = i + 1
        Cells(PersonSheet, i, Id).String = ._Phone1 : i = i + 1
        Cells(PersonSheet, i, Id).String = ._Phone2 : i = i + 1
        Cells(PersonSheet, i, Id).String = ._FAX : i = i + 1
        Cells(PersonSheet, i, Id).String = ._EMail : i = i + 1
        Cells(PersonSheet, i, Id).String = ._Note : i = i + 1
    End With
    
    SaveById = True
    
End Function

内容を解説します。

  1. 読込みと同様に個別データの読込み関数と全データの読込み関数を別で作ります。
  2. UBound関数で分類数を取得します。
  3. データ数分だけ、データの書込み処理を行います。この時何か不具合があればFor文から抜け出します。
  4. もし既存のデータがあると次回の読み込み時に誤動作する可能性があるので、最終データの次の行のId列を空白にしておきます。
createUnoDialog - 自作ダイアログの利用

IDEにてモジュール以外にダイアログを追加して、ボタンやテキストボックスなどのコントロールを配置することで、自作のダイアログを利用する事ができます。但し、ダイアログを扱うには多くの知識が必要になるため、敷居が高いのは否めません。
そこで、それがなるべく簡単になるよう、必要最低限の機能を説明したいと思います。

まず、IDEのモジュール名タブにてマウスの右クリックをし、「挿入」から「BASICダイアログ」を選びます。すると、何も配置されていないダイアログが作成されます。そして、「dlgSample」と名称を変更します。

次に、これをマクロで表示させるためのサンプルコードを下記に示します。

Sub Main
    
    Dim oDialog As Object
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgSample)
    With oDialog
        .execute
        .dispose
    End With
    
End Sub

これは、ただ単にダイアログを表示して、ウィンドウの閉じるボタンで終了するだけのものです。

VBAではダイアログ(フォーム)に直接コードを書きますが、OOoBasicはモジュールにコードを記述しなくてはなりません。
これは僕流のやり方なのですが、僕はダイアログと同じ名前のモジュールを用意して、これをVBAのフォームに付随するコードのように使っています。例えば、今回の「dlgSample」に対し「mdlSample」というのを作り、そこにコードを記述していきます。今後このブログ中でもいくつかのダイアログを扱いますが、全てこうしたコードの記述を行いますので、留意下さい。
こうする事のメリットとして、以下のようなコードを記述する事ができることにあります。

mdlSample
Sub Show
    
    Dim oDialog As Object
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgSample)
    With oDialog
        .execute
        .dispose
    End With
    
End Sub
Module1
Sub Main
    mdlSample.Show
End Sub

ここで、Module1のMainを実行するとダイアログが表示されます。VBAではUserForm1.Showとして使う事ができるのと似ていませんか?
また、配置したコントロールも同様に扱えるような工夫ができます。

データ読込み「担当」

工程型を使って、「担当」シートからデータを取り出す仕組みを作りますが、ここで、準備で紹介したシート選択、セルの値取得関数を利用します。
担当に関するプログラムをまとめるため、新しいモジュールを作成して「mdlPerson」とし、以下はそのモジュール内に書きます。

まず担当データを取得する関数を作成し、その他に必要な設定を「mdlMain」に追記します。

mdlPerson
Option Explicit '---(1)

Type PersonType '---(2)
    _Id As Integer
    _Name As String
    _Phone1 As String
    _Phone2 As String
    _FAX As String
    _EMail As String
    _Note As String
End Type

Public PersonSheetName As String '---(3)
Public PersonSheet As Object '---(4)
 
Public Persons() As PersonType
 
Public Function LoadAll As Integer '---(5)
    
    Dim i As Integer
    
    If flgLoaded Then
        LoadAll = UBound(Persons())
        Exit Function
    End If
    
    Redim Preserve Persons(0)
    
    i = 1
    Do
        If Cells(PersonSheet, 1, i + 1).Value = 0  Then Exit Do '---(6)
        Redim Preserve Persons(i)
        LoadById(Persons(i), i)
        i = i + 1
    Loop
    
    flgLoaded = True
    LoadAll = i - 1
    
End Function

Public Function LoadById(Person As PersonType, _
    ByVal Id As Integer) As Boolean '---(5)
    
    Dim i As Integer
    
    Id = Id + 1
    If Id < 2 Or Cells(PersonSheet, 1, Id).Value = 0 Then '---(7)
        LoadById = False
        Exit Function
    End If
    
    i = 1 '---(8)
    With Person
        ._Id = Cells(PersonSheet, i, Id).Value: i = i + 1
        ._Name = Cells(PersonSheet, i, Id).String: i = i + 1
        ._Phone1 = Cells(PersonSheet, i, Id).String: i = i + 1
        ._Phone2 = Cells(PersonSheet, i, Id).String: i = i + 1
        ._FAX = Cells(PersonSheet, i, Id).String: i = i + 1
        ._EMail = Cells(PersonSheet, i, Id).String: i = i + 1
        ._Note = Cells(PersonSheet, i, Id).String: i = i + 1
    End With
    
    LoadById = True
    
End Function

内容について説明します。

  1. 変数の宣言を強制します。OOoBasicでは(VBAでも)、変数は宣言せずとも使用できるのですが、そのままマクロを作成していると、タイプミスなどでおかしな挙動をした時のデバッグが大変です。そこで、可能な限りこのオプションを使用することをお薦めします。
  2. 担当型を宣言します。
  3. 後々のためにデータシート名を記録する変数を用意します。
  4. データシート用のオブジェクトを生成しておきます。
  5. 個別データの読み込み関数と全データの読み込み関数を別で作ります。
  6. Idデータのセルを確認し、Idの記載が無ければ終了します。
  7. 不正なId値を指定された場合にFalseを返し、処理を終了します。
  8. 自作のCells関数は、1から始まるので左端の列を指定し、データを取り出す度に列を移動しながら全てのデータを取得します。

そして「mdlMain」モジュールに下記を追加します。これは今後の項目や工程の設定も同じようにすることで、今後のコーディングを楽にするための工夫です。そして今後、読み込みや書込み等のマクロを実行する際には、必ずmdlMain.Initiarizaという一文を入れておきます。

mdlMain
'Public Sub Initializeへ追記
PersonSheetName = "担当"
PersonSheet = Sheets(PersonSheetName)
データ交換、コピー「工程」

読込んだデータを交換したりコピーする関数を定義します。

これまでと同様に「mdlSchedule」に追記していきます。

mdlSchedule
Public Sub Swap(Data1 As ScheduleType, Data2 As ScheduleType) '---(1)
    
    Dim wk As ScheduleType
    
    Copy(Data1, wk)
    Copy(Data2, Data1)
    Copy(wk, Data2)
    
End Sub

Public Sub Copy(Src As ScheduleType, Dst As ScheduleType) '---(2)
    
    With Src
        'Dst._Id = ._Id
        Dst._Name = ._Name
        Dst._ItemId = ._ItemId
        Dst._PlanBegin = ._PlanBegin
        Dst._PlanEnd = ._PlanEnd
        Dst._PlanColor = ._PlanColor
        Dst._ActBegin = ._ActBegin
        Dst._ActEnd = ._ActEnd
        Dst._ActColor = ._ActColor
        Dst._LineType = ._LineType
        Dst._Weight = ._Weight
    End With
    
End Sub

内容について説明します。

  1. 後に作るコピー用関数を使って、データ交換処理を行います。
  2. コピー用関数を定義します。
データ書込み「工程」

読込みと同様に、「mdlSchedule」に追記します。

mdlSchedule
Public Function SaveAll() As Integer'---(1)
    
    Dim i As Integer
    
    For i = 1 To UBound(Schedules())'---(2)
        If Not SaveById(Schedules(i)) Then Exit For'---(3)
    Next i
    Cells(ScheduleSheet, 1, i + 1).String = ""'---(4)
    
    SaveAll = i - 1
    
End Function
 
Public Function SaveById(Schedule As ScheduleType) As Boolean'---(1)
    
    Dim i As Integer
    Dim Id As Integer
    
    i = 1
    With Schedule
        Id = ._Id + 1
        Cells(ScheduleSheet, i, Id).Value = ._Id : i = i + 1
        Cells(ScheduleSheet, i, Id).String = ._Name : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._ItemId : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._PlanBegin : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._PlanEnd : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._PlanColor : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._ActBegin : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._ActEnd : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._ActColor : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._LineType : i = i + 1
        Cells(ScheduleSheet, i, Id).Value = ._Weight : i = i + 1
    End With
    
    SaveById = True
    
End Function

内容を解説します。

  1. 読込みと同様に個別データの読込み関数と全データの読込み関数を別で作ります。
  2. UBound関数で分類数を取得します。
  3. データ数分だけ、データの書込み処理を行います。この時何か不具合があればFor文から抜け出します。
  4. もし既存のデータがあると次回の読み込み時に誤動作する可能性があるので、最終データの次の行のId列を空白にしておきます。
データ読込み「工程」

工程型を使って、「工程」シートからデータを取り出す仕組みを作りますが、ここで、準備で紹介したシート選択、セルの値取得関数を利用します。
工程に関するプログラムをまとめるため、新しいモジュールを作成して「mdlSchedule」とし、以下はそのモジュール内に書きます。

まず工程データを取得する関数を作成し、その他に必要な設定を「mdlMain」に追記します。

mdlSchedule
Option Explicit '---(1)
 
Type ScheduleType '---(2)
    _Id As Integer
    _Name As String
    _ItemId As Integer
    _PlanBegin As Date
    _PlanEnd As Date
    _PlanColor As Long
    _ActBegin As Date
    _ActEnd As Date
    _ActColor As Long
    _LineType As Integer
    _Weight As Long
End Type
 
Public ScheduleSheetName As String '---(3)
Public ScheduleSheet As Object
 
Public Schedules() As ScheduleType '---(4)
 
Public Function LoadAll() As Integer '---(5)
    
    Dim i As Integer
    
    If flgLoaded Then
        LoadAll = UBound(Schedules())
        Exit Function
    End If
    
    Redim Preserve Schedules(0)
    
    i = 1
    Do
        If Cells(ScheduleSheet, 1, i + 1).Value = 0  Then Exit Do '---(6)
        Redim Preserve Schedules(i)
        LoadById(Schedules(i), i)
        i = i + 1
    Loop
    
    flgLoaded = True
    LoadAll = i - 1
    
End Function
 
Public Function LoadById(Schedule As ScheduleType, _
    ByVal Id As Integer) As Boolean '---(5)
    
    Dim i As Integer
    
    Id = Id + 1
    If Id < 2 Or Cells(ScheduleSheet, 1, Id).Value = 0 Then '---(7)
        LoadById = False
        Exit Function
    End If
    
    i = 1 '---(8)
    With Schedule
        ._Id = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._Name = Cells(ScheduleSheet, i, Id).String: i = i + 1
        ._ItemId = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._PlanBegin = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._PlanEnd = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._PlanColor = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._ActBegin = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._ActEnd = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._ActColor = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._LineType = Cells(ScheduleSheet, i, Id).Value: i = i + 1
        ._Weight = Cells(ScheduleSheet, i, Id).Value: i = i + 1
    End With
    
    LoadById = True
    
End Function

内容について説明します。

  1. 変数の宣言を強制します。OOoBasicでは(VBAでも)、変数は宣言せずとも使用できるのですが、そのままマクロを作成していると、タイプミスなどでおかしな挙動をした時のデバッグが大変です。そこで、可能な限りこのオプションを使用することをお薦めします。
  2. 分類型を宣言します。
  3. 後々のためにデータシート名を記録する変数を用意します。
  4. データシート用のオブジェクトを生成しておきます。
  5. 個別データの読み込み関数と全データの読み込み関数を別で作ります。
  6. Idデータのセルを確認し、Idの記載が無ければ終了します。
  7. 不正なId値を指定された場合にFalseを返し、処理を終了します。
  8. 自作のCells関数は、1から始まるので左端の列を指定し、データを取り出す度に列を移動しながら全てのデータを取得します。

そして「mdlMain」モジュールに下記を追加します。これは今後の項目や工程の設定も同じようにすることで、今後のコーディングを楽にするための工夫です。そして今後、読み込みや書込み等のマクロを実行する際には、必ずmdlMain.Initiarizaという一文を入れておきます。

mdlMain
'Public Sub Initializeへ追記
ScheduleSheetName = "工程"
ScheduleSheet = Sheets(ScheduleSheetName)
データ交換、コピー「項目」

読込んだデータを交換したりコピーする関数を定義します。

これまでと同様に「mdlItem」に追記していきます。

mdlItem
Public Sub Swap(Data1 As ItemType, Data2 As ItemType) '---(1)
    
    Dim wk As ItemType
    
    Copy(Data1, wk)
    Copy(Data2, Data1)
    Copy(wk, Data2)
    
End Sub
 
Public Sub Copy(Src As ItemType, Dst As ItemType) '---(2)
    
    With Src
        'Dst._Id = ._Id
        Dst._Name = ._Name
        Dst._CategoryId = ._CategoryId
        Dst._PersonId = ._PersonId
        Dst._Note = ._Note
        Dst._Complete = ._Complete
        Dst._Status = ._Status
        Dst._Hyperlink = ._Hyperlink
        Dst._UpperId = ._UpperId
        Dst._Spare = ._Spare
    End With
    
    Dim i As Integer
    
    For i = 1 To 20
        setProgress(Dst, i, getProgress(Src, i))
    Next i
    
End Sub

内容について説明します。

  1. 後に作るコピー用関数を使って、データ交換処理を行います。
  2. コピー用関数を定義します。
MsgBox - メッセージの表示

VB/VBAではおなじみで、OOoBasicでも使えます。ですが、vb...という名称は定義されていないのでこれを定義する事でVBAのコードをそのまま流用する事が可能となります。

[用法]
MsgBox(メッセージ[, 設定[, タイトル]])
[例]
MsgBox "テストです"
MsgBox "もう一度テストしても良いですか?",4
If MsgBox("エラーが発生しました", 5 + 48, "エラー") = 4 Then
    MsgBox "再挑戦"
Else
    MsgBox "止めます"
End If

ここで、設定に入れた「4」や「5+48」というのはどんなボタンやアイコンを配置するかを設定するためのものですが、数値で覚えるのは酷です。また、戻り値によりどのボタンを押したのかを判断する事もできますが、同様に数値を覚えるのは酷です。そこで、VB/VBAと同じ定数を定義する事でちょっと使いやすくしてみます。

Public Const vbOKOnly = 0
Public Const vbOkCancel = 1
Public Const vbAbortRetryIgnore = 2 '注) OOoBasicにはありません
Public Const vbYesNoCancel = 3
Public Const vbYesNo = 4
Public Const vbRetryCancel = 5
Public Const vbCritical = 16
Public Const vbQuestion = 32
Public Const vbExclamation = 48
Public Const vbInfomation = 64
Public Const vbDefaultButton1 = 0
Public Const vbDefaultButton2 = 256
Public Const vbDefaultButton3 = 512
 
Public Const vbOK = 1
Public Const vbCancel = 2
Public Const vbAbort = 3 '注) OOoBasicにはありません
Public Const vbRetry = 4
Public Const vbIgnore = 5
Public Const vbYes = 6
Public Const vbNo = 7

これを使って先ほどのテストを書き直すと

MsgBox "テストです"
MsgBox "もう一度テストしても良いですか?",vbYesNoCancel
If MsgBox("エラーが発生しました", vbRetryCancel + vbExclamation, _
    "エラー") = vbRetry
    MsgBox "再挑戦"
Else
    MsgBox "止めます"
End If

となり、多少可読性が向上しますしVBAのコードをそのままコピー&ペーストが可能になります。

データ書込み「項目」

読込みと同様に、「mdlItem」に追記します。

mdlItem
Public Function SaveAll() As Integer '---(1)
    
    Dim i As Integer
    
    For i = 1 To UBound(Items()) '---(2)
        If Not SaveById(Items(i)) Then Exit For '---(3)
    Next i
    Cells(ItemSheet, 1, i + 1).String = "" '---(4)
    
    SaveAll = i - 1
    
End Function
 
Public Function SaveById(Item As ItemType) As Boolean '---(1)
    
    Dim i As Integer
    Dim Id As Integer
    
    i = 1
    With Item
        Id = ._Id + 1
        Cells(ItemSheet, i, Id).Value = ._Id : i = i + 1
        Cells(ItemSheet, i, Id).String = ._Name : i = i + 1
        Cells(ItemSheet, i, Id).Value = ._CategoryId : i = i + 1
        Cells(ItemSheet, i, Id).Value = ._PersonId : i = i + 1
        Cells(ItemSheet, i, Id).String = ._Note : i = i + 1
        Cells(ItemSheet, i, Id).Value = ._Complete : i = i + 1
        Cells(ItemSheet, i, Id).Value = ._Status : i = i + 1
        Cells(ItemSheet, i, Id).String = ._Hyperlink : i = i + 1
        Cells(ItemSheet, i, Id).Value = ._UpperId : i = i + 1
        Cells(ItemSheet, i, Id).String = ._Spare : i = i + 1
    End With
    
    Dim Num As Integer
    
    For Num = 1 To 20
        Cells(ItemSheet, i, Id).Value = getProgress(Item, Num)
        i = i + 1
    Next Num
    
    SaveById = True
    
End Function

内容を解説します。

  1. 読込みと同様に個別データの読込み関数と全データの読込み関数を別で作ります。
  2. UBound関数で分類数を取得します。
  3. 項目数分だけ、データの書込み処理を行います。この時何か不具合があればFor文から抜け出します。
  4. もし既存のデータがあると次回の読み込み時に誤動作する可能性があるので、最終データの次の行のId列を空白にしておきます。
COPYRIGHT(C) 2004 POWERD BY FC2 ALLRIGHT RESERVED.
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。