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

編集や描画を行う際にデータを扱いやすくするため、管理用データを作成します。ここで、この管理データにBinという名前を付けることにします。

まずモジュールを追加して「mdlBin」とします。

Type BinType
    _Type As Integer
    _Id As Integer
    _Depth As Integer
    _Row As Integer
End Type
 
Public Bins() As BinType

Bin型の構造体とその配列を宣言します。この構造体にある_TypeはこのBinに入れたデータが分類か項目かを区別するために使用します。
ここに入れる値は以下のような変数を利用します。

Public Const BINTYPE_CATEGORY = 1
Public Const BINTYPE_ITEM = 2

まず、このBinを追加するための関数を作ります。

Public Function Count As Integer
    Count = UBound(Bins())
End Function
 
Public Sub AddBins(_Type As Integer, _Id As Integer, _Depth As Integer)
    
    Dim i As Integer
    
    i = Count + 1
    Redim Preserve Bins(i)
    
    With Bins(i)
        ._Type = _Type
        ._Id = _Id
        ._Depth = _Depth
    End With
    
End Sub

次に、保存されたデータからこのBinを生成する関数を作ります。

Public Sub CreateBins(Optional setAll Boolean)
    
    Dim i As Integer, j As Integer, k As Integer
    
    If IsMissing(setAll) Then setAll = True
    
    mdlCategory.LoadAll
    mdlItem.LoadAll
    mdlSchedule.LoadAll
    mdlPerson.LoadAll
    
    Redim Preserve Bins(0)
    
    For i = 1 To UBound(Categories())
        AddBins(BINTYPE_CATEGORY, i, 0)
        If Categories(i)._Visible Then
            For j = 1 To UBound(Items())
                If Items(j)._CategoryId = i And _
                    (setAll Or Items(j)._Draw) Then
                        AddBins(BINTYPE_ITEM, j, 1)
                End If
            Next j
        End If
    Next i
    
    setItemsBeginAndEndDate
    
End Sub

この関数は、今後チャートの描画にも使用しますので、多少細工があります。
setAllという引数があるのですが、これは非表示に設定された分類を区別して取り扱うためです。ここにあるOptionalというのは、関数を呼び出し時に指定しなくてもエラーになりません。全データを扱う時はここにTrueを入れ、非表示の分類データを扱わない時はFalseを入れます。そして、指定しない時には全データを扱います。

処理の内容を簡単に説明すると、分類データを順に取得して、その分類に割り当てられている項目データを探して分類データの次に登録しています。これを分類データの回数だけ繰り返します。

次回はこれを使って、管理用のダイアログを作成します。

スポンサーサイト

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

セルの値取得、入力(補足)

ちょっと強引なやり方をすれば、限りなくExcelに近づけられることがわかったので紹介します。まず、重要な要素として言えるのがOOoBasicではモジュールもオブジェクトとして扱う事ができるということです。

モジュールを追加して、名称を「mdlExcelSheet」とします。そして、そのモジュールに下記のコードを追加します。

Option Explicit
Dim oSheet As Object
 
Function Cells(Row As Integer, Col As Integer) As Object
    
    If IsNull(oSheet) Then _
        oSheet = ThisComponent.CurrentController.ActiveSheet
    Cells = oSheet.getCellByPosition(Col - 1, Row - 1)
    oSheet = Nothing
    
End Function

ここでは、ExcelのCellsが「列、行」の順で指定するのに対し、OOoBasicのgetCellByPositionでは「行、列」で指定する事の違いと、セルの数え方が0から数えるのに対し1から数えるという違いを吸収できるように考えておきます。

次にマクロを実行させるモジュールを追加して、下記のコードを追記します。

Function Sheets(SheetName As String)
    
    mdlExcelSheet.oSheet = ThisComponent.Sheets.getByName(SheetName)
    Sheets = mdlExcelSheet
    
End Function

これを利用すると、下記のようなコードでセルを参照する事ができるようになります。

Sub Main
    
    MsgBox Sheets("表1").Cells(2,1).Value
    
End Sub

また選択中のシートを操作する場合、

Function ActiveSheet
    
    mdlExcelSheet.oSheet = ThisComponent.CurrentController.ActiveSheet
    ActiveSheet = mdlExcelSheet
    
End Function

という関数を追加する事で次のように実現できます。

Sub Main
    
    ActiveSheet.Cells(2,1).Value = 123
    
End Sub

今後、OpenOffice.orgはExcelとのマクロの互換性が向上するらしいのでいつまで必要かはわかりませんが、いろいろと使える手法ではないかなとも思います。モジュールがクラスみたいにNewステートメントが使えるようになるともっといいですね。

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

進捗データ管理ダイアログ その4

IDEでダイアログを追加し、名称を「dlgEditProgress」とし必要なコントロールを追加します。配置後は下図となります。


そして、いつも通りモジュールを追加して「mdlEditProgress」とします。

Option Explicit
 
Private oDialog As Object
 
Private btnOK As Object
Private btnDel As Object
Private lstProgress As Object
 
Public dlgEditProgress_btnOK_Label As String
Public dlgEditProgress_btnDel_Label As String
 
Private oActionListener As Object
Private flgUpdate As Boolean

まず、変数宣言の強制をしてから、各種コントロール、表示、アクションリスナー用変数を宣言します。

Sub Show
    Initialize
    With oDialog
        .execute
        .dispose
    End With
End Sub
 
Sub Initialize
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgEditProgress)
    'mdlText.MakeDialogModuleTemplete(oDialog)
    
    With oDialog
        btnOK = .getControl("btnOK")
        btnDel = .getControl("btnDel")
        lstProgress = .getControl("lstProgress")
    End With

    oActionListener = _
        CreateUnoListener("dlgEditProgressActionListener_", _
            "com.sun.star.awt.XActionListener")
    
    btnOK.addActionListener(oActionListener)
    btnDel.addActionListener(oActionListener)
    lstProgress.addActionListener(oActionListener)
    
    btnOK.Label = dlgEditProgress_btnOK_Label
    btnDel.Label = dlgEditProgress_btnDel_Label
    
    setlstProgress
    
End Sub

ダイアログを表示するためのShow関数を作成し、初期化用のInitialize関数を作成します。これまでと同様にダイアログを取得してからコントロールを変数に割当て、アクションリスナーを追加、表示設定を行います。
また、進捗データの一覧にsetlistProgress関数を作成し利用していますが、コードは下記となります。

Sub setlstProgress
    
    Dim i As Integer
    Dim s As String
    
    clearListBox(lstProgress)
    
    For i = 1 To 20
        s = i & " : "
        If Progresses(i) > FirstDate Then
            s = s & Progresses(i)
        End If
        
        lstProgress.addItem(s, i - 1)
    Next i
    
End Sub

mdlMain内にあるclearListBox関数で登録済みの内容を消去してから、進捗データをリストボックスに追加していきます。

次にそれぞれのコントロールの動作を作成します。

Private Sub lstProgress_actionPerformed
    
    Dim i As Integer
    
    i = lstProgress.getSelectedItemPos + 1
    If i < 1 Then Exit Sub
    
    Dim wk As Date
    
    wk = mdlCalendar.Show(Now(), CALENDARTYPE_SELECT)
    
    If 0 < wk Then
        Progresses(i) = wk
        mdlItem.setAllProgress(i)
        setlstProgress
    End If
    
End Sub

これはリストボックスをダブルクリックした場合の処理で、選択済みの位置を取得してからカレンダーダイアログを表示して日時を取得します。そして取得した日付から、前回作成したsetAllProgress関数を使って進捗データを生成して、リストを更新します。

Private Sub btnDel_actionPerformed

    Dim i As Integer
    
    i = lstProgress.getSelectedItemPos + 1
    If i < 1 Then Exit Sub
    
    mdlItem.clearAllProgress(i)
    setlstProgress
    
End Sub

これは、削除ボタン用の関数で、選択された進捗データをcleaeAllProgress関数で初期化し、リストを更新しています。

Private Sub dlgEditProgressActionListener_actionPerformed(oEvent)
    Select Case oEvent.Source.getModel().Name
        Case "btnOK"
            oDialog.endExecute
        Case "btnDel"
            btnDel_actionPerformed
        Case "lstProgress"
            lstProgress_actionPerformed
        Case Else
        
    End Select
End Sub
 
Private Sub dlgEditProgressActionListener_disposing(): End Sub

最後にアクションリスナー用の関数を作成します。ここでbtnOKボタンは一文で命令が終了するのであえて動作用の関数を生成しませんでした。これも従来通り、呼び出し元の名称から処理を分岐してそれぞれの動作を行わせます。また、終了時のエラーを回避するためdisposing関数も宣言しておきます。

以上で進捗データ管理ダイアログは完成です。

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

進捗データ管理ダイアログ その3

前回作成した項目データのメンバ変数から、進捗状況設定のための関数を作成します。

Sub setAllProgress(Target As Integer)
    
    Dim i As Integer
    Dim tmp As Date
    Dim wk As Object
    
    tmp = Progresses(Target)
    
    For i = 1 To Count
        wk = Items(i)
        
        If wk._BeginDate < tmp Then
            setProgress(wk, Target, wk._Progress)
        Else
            If wk._BeginDate = wk._Progress Then
                setProgress(wk, Target, tmp)
            Else
                setProgress(wk, Target, wk._Progress)
            End If
        End If
        
        MsgBox getProgress(wk, Target)
        
    Next i
    
End Sub

作成したい進捗データの番号を引数とし、その進捗データ配列に登録されている日付と項目データの内容を比較し、イナズマ線の描画に必要なデータを項目に設定していきます。
次に不要になった進捗情報を消去する関数を作成して、進捗情報を操作する準備が完全に整います。

Sub clearAllProgress(Target As Integer)
    
    Dim i As Integer
    
    Progresses(Target) = 0
    For i = 1 To Count
        setProgress(Items(i), Target, 0)
    Next i
    
End Sub

次回は、やっとダイアログの作成です。ずいぶん遅くなったように感じられるかもしれませんが、ここまで準備をしておくとダイアログの作成が非常に楽になります。

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

進捗データ管理ダイアログ その2

次に進捗データ管理を容易にするため、項目データに設定されている全工程の開始日・終了日、現在の実績終了日を取得するようにします。
まず、追加するメンバ変数を示します。

Type ItemType
    ~中略~
    _BeginDate As Date
    _EndDate As Date
    _Progress As Date
End Type

そして、このメンバ変数を初期化するために以下の関数を作成します。

Public Sub setItemsBeginAndEndDate
    
    Dim i As Integer
    
    For i = 1 To UBound(Items())
        setItemBeginAndEndDate(Items(i))
    Next i
    
End Sub
 
Public Sub setItemBeginAndEndDate(Item)
    
    Dim i As Integer
    Dim wk
    Dim tmp As Date
    
    Item._BeginDate = 0
    Item._EndDate = 0
    Item._Progress = 0
    
    For i = 1 To UBound(Schedules())
        
        If Item._Id = Schedules(i)._ItemId Then
            
            wk = Schedules(i)
            If wk._PlanBegin <> 0 And _
                (Item._BeginDate = 0 Or _
                    wk._PlanBegin < Item._BeginDate) Then _
                        Item._BeginDate = wk._PlanBegin
            If wk._PlanEnd <> 0 And _
                Item._EndDate < wk._PlanEnd Then _
                    Item._EndDate = wk._PlanEnd
            
            tmp = wk._PlanBegin
            If FirstDate < wk._ActEnd Then
                tmp = wk._ActEnd
            ElseIf FirstDate < wk._ActBegin Then
                tmp = Int(wk._ActBegin) + 1
            Else
                tmp = Item._BeginDate
            End If
            
            If Item._Progress < tmp Then Item._Progress = tmp
            
        End If
        
    Next i
    
    If Item._EndDate < Item._BeginDate Then _
        Item._EndDate = Int(Item._BeginDate) + 1
    
End Sub

これで下準備が整いましたので、次回は進捗データの設定・削除用関数を作成します。

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

進捗データ管理ダイアログ その1

ここで言う進捗データ管理とは、一般的にイナズマ線と呼ばれるものです。まず、項目データにあるProgress1~20を管理するために、Progressという日付データの配列を宣言します。そして、このデータを読込み、保存する関数を作成します。

Public Progresses(20) As Date
 
Sub LoadProgress
    
    Dim i  As Integer
    
    For i = 1 To 20
        Progresses(i) = Cells(ItemSheet, i + 10, 1).Value
    Next i
    
End Sub
 
Sub SaveProgress

    Dim i  As Integer
    
    For i = 1 To 20
        Cells(ItemSheet, i + 10, 1).Value = Progresses(i)
    Next i
    
End Sub

ここで、データの保存先は項目データの進捗データの一番上(ヘッダー行)としています。
そして、mdlItem.LoadAll関数に進捗データの読み込み、mdlItem.SaveAll関数に進捗データの保存を追記します。

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

カレンダーダイアログ 番外編

カレンダーダイアログを利用するように、工程編集ダイアログの修正を行います。

前回詳しく書かなかったのですが、工程編集ダイアログのInitialize関数にて、

txtPlanBegin.addMouseListener(oMouseListener)
txtPlanEnd.addMouseListener(oMouseListener)
txtActBegin.addMouseListener(oMouseListener)
txtActEnd.addMouseListener(oMouseListener)

という記述を既にしており、準備はしていました。後は、クリック時の処理を作成し、マウスリスナーに必要な命令を追加するだけで完成です。
以下にクリック時の処理を示します。

Private Sub txtDate_mousePressed(oEvent)
    
    If Not State2Bool(chkCalendar) Then Exit Sub
    
    If flgCalendar Then Exit Sub
    
    flgCalendar = True
    
    Dim wk As Date
    wk = mdlCalendar.Show(CDate(oEvent.Source.Text), CALENDARTYPE_SELECT)
    
    Select Case oEvent.Source.getModel.Name
        Case "txtPlanEnd","txtActEnd"
            wk = wk + 1
    End Select
    
    If FirstDate < wk Then oEvent.Source.Text = wk
    
    flgCalendar = False
    
End Sub

まず、chkCalendarコントロールの状態を確認し、カレンダーを使用することにチェックを入れていなければ処理を中断します。
また、カレンダーの表示には多少時間がかかるので、繰り返しクリックをされるとエラーが発生することがあるので、flgCalendar変数を確認し、動作中であれば処理を中断し、動作中でなければ動作中のフラグを設定して処理を継続します。
ここで、カレンダーダイアログを日付選択モードで表示し、選択した日付でそれぞれのテキストボックスの内容を更新するのですが、データの関係上、終了日には1を加算しておきます。

次に、マウスリスナーの関数を変更します。

Sub dlgEditScheduleMouseListener_mousePressed(oEvent As Object)
    Select Case oEvent.Source.getModel().Name
        Case "imgPlanColor", "imgActColor"
            imgColor_mousePressed(oEvent)
        Case "txtPlanBegin","txtPlanEnd","txtActBegin","txtActEnd"
            txtDate_mousePressed(oEvent)
        Case Else
        
    End Select
End Sub

これでテキストボックスをクリックすることにより、日付の変更をカレンダーダイアログで行う事ができるようになります。

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

カレンダーダイアログ その4

次はボタンのの動作を指定します。ボタンには日付と設定があるのですが、日付ボタンは名称が多いので分岐の条件は「btnSet」かそれ以外ということにします。そして、日付ボタンを押したときは、呼び出し元のオブジェクトを引数にしたbtnDay_Click関数に渡して処理をすることにします。

Private Sub dlgCalendarActionListener_actionPerformed(oEvent)

    Select Case oEvent.Source.getModel().Name
        Case "btnSet"
            btnSet_Click
        Case Else
            btnDay_Click(oEvent.Source)
    End Select
End Sub

Private Sub dlgCalendarActionListener_disposing(): End Sub

日付ボタンをクリックした時の処理を示します。

Private Sub btnDay_Click(Button As Object)
    
    Dim i As Integer
    
    i = CInt(Button.getModel.Label)
    If  i < 1 Then Exit Sub
    
    Dim wk As Date
    
    wk = DateSerial(Year(FirstDate) + Int(scbMonth.Value / 12), _
        (scbMonth.Value mod 12) + 1, i)
    SelectedDate = wk
    
    If CalendarType = CALENDARTYPE_SELECT Then
        oDialog.endExecute
        Exit Sub
    End If
    
    mdlHoliday.Change(wk)
    
    If mdlHoliday.IsHoliday(wk) Then
        Button.getModel.TextColor = RGB(255,0,0)
    Else
        Button.getModel.TextColor = RGB(0,0,0)
    End If
    
End Sub

まず、日付ボタンのラベルから日付を取得し、DateSerial関数で日時の情報を生成します。
ここで、選択用に呼び出した時は、これでダイアログを閉じます。休日設定用に呼び出した時は、選択した日付の休日と平日を切り替えて、切り替え後に休日だったら赤表示で平日だったら黒表示にします。

また、設定ボタンを押した後はダイアログを閉じるだけなので、以下のコードとなります。

Private Sub btnSet_Click
    oDialog.endExecute
End Sub

以上でカレンダーダイアログは完成ですが、次回はこれを用いて工程データ編集ダイアログを改造を紹介します。

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

カレンダーダイアログ その3

次はスクロールバーの動作を指定します。スクロールバーを動作させるとAdjustmentListenerが呼び出されるので、呼び出し元の名前を判別して処理を切り分けるコードを書きます。ただし、ここではスクロールバーが一つしか無いのでちょっと寂しいですが...

Private Sub dlgCalendarAdjustmentListener_adjustmentValueChanged(oEvent)
    Select Case oEvent.Source.getModel().Name
        Case "scbMonth"
            scbMonth_Changed
        Case Else
        
    End Select
End Sub
 
Private Sub dlgCalendarAdjustmentListener_disposing: End Sub

スクロールバー用のscbMonth_Change関数を書きます。

Private Sub scbMonth_Changed
    getMonth(scbMonth.Value)
End Sub
 
Private Sub getMonth(Value As Integer)
    
    Dim y As Integer
    Dim m As Integer
    
    y = Int(Value / 12) + Year(FirstDate)
    m = (Value mod 12) + 1
    
    lblMonth.Text = y & "/" & m
    
    setDays(y,m)
    
End Sub

getMonth関数はスクロールバーの値から年月を計算して、日付ボタンの表示を更新します。
ここで、modは余りの計算を意味します。スクロールバーの値を12で割って整数にすると年数が取得できるので、これに工程で扱う最初の日付であるFirstDateの年と足します。次に値を12で割った余りから月が取得できます。
こうして取得した年月を前述したsetDays関数に渡して、日付表示を更新します。

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

カレンダーダイアログ その2

IDEにて、「BASIC ダイアログ」を挿入し、名称を「dlgCalendar」とします。そして、カレンダーに必要なコントロールを配置すると下図のようになります。これを作る時に気をつける事として、日付用のボタンは名称をいちいち設定するのが面倒なので連続して作成します。また、一ヶ月の最大日数は31日ですが、37個のコントロールを配置します。


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

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

Option Explicit
 
Private oDialog As Object
 
Private lblMonth As Object
Private scbMonth As Object
Private btnDay(36) As Object
Private btnSet As Object
 
Public dlgCalendar_btnSet_Label As String
 
Private oActionListener As Object
Private oAdjustmentListener As Object
 
Private SelectedDate As Date
Private CalendarType As Integer
 
Public Const CALENDARTYPE_EDIT = 0
Public Const CALENDARTYPE_SELECT = 1

いつも通り、ダイアログとコントロール、リスナー用の変数を宣言します。また、カレンダーには日付選択と休日設定の2種類があるので、これらの種類を記録させるための変数を宣言します。

Public Function Show(TargetDate As Date, wkType As Integer)
    
    If TargetDate < FirstDate Then
        SelectedDate = Now()
    Else
        SelectedDate = TargetDate
    End If
    
    CalendarType = wkType
    
    Initialize
    setMonth(SelectedDate)
    
    If CalendarType = CALENDARTYPE_SELECT Then
        SelectedDate = 0
        btnSet.setVisible(False)
    End If
    
    With oDialog
        .execute
        .dispose
    End With
    
    Show = SelectedDate
    
End Function

ダイアログを表示するための関数ですが、最初に表示する年月とカレンダーの種類を指定するように引数を設けます 。また、選択用の時には日付を選択直後にダイアログを閉じることとしますのでbtnSetボタンを非表示にします。
ダイアログ終了時に選択した日付を戻り値として返します。

Private Sub Initialize
    
    Dim i As Integer
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgCalendar)
    
    oAdjustmentListener = _
        CreateUnoListener("dlgCalendarAdjustmentListener_", _
            "com.sun.star.awt.XAdjustmentListener")
    oActionListener = _
        CreateUnoListener("dlgCalendarActionListener_", _
            "com.sun.star.awt.XActionListener")
    
    With oDialog
        lblMonth = .getControl("lblMonth")
        scbMonth = .getControl("scbMonth")
        btnSet = .getControl("btnSet")
        For i = 0 To UBound(btnDay())
            btnDay(i) = .getControl("CommandButton" & i + 1)
            btnDay(i).addActionListener(oActionListener)
            'btnDay(i).Label = ""
        Next i
    End With
    
    scbMonth.addAdjustmentListener(oAdjustmentListener)
    
    btnSet.Label = dlgCalendar_btnSet_Label
    btnSet.addActionListener(oActionListener)
    
End Sub

日付ボタンは扱いを容易にするために配列で宣言したので、多少これまでとは違って見えるかもしれませんが、基本的にやっていることは同じです。
また、mdlMainモジュールのInitialize関数に下記を追加しておきます。

dlgCalendar_btnSet_Label = ControlLabelString("設定")

また、リスナーは日付ボタンに配置する関係上、コントロール変数を初期化する前に宣言しています。

Private Sub setMonth(TargetDate As Date)
    
    Dim i As Integer
    Dim y As Integer
    Dim m As Integer
    
    y = Year(TargetDate)
    m = Month(TargetDate)
    
    lblMonth.Text = y & "/" & m
    scbMonth.Value = (y - Year(FirstDate)) * 12 + m - 1
    
    setDays(y,m)
    
End Sub
 
Private Sub setDays(y As Integer, m As Integer)
    
    Dim wk As Date
    Dim i As Integer
    Dim week As Integer
    
    scbMonth.setVisible(False)
    
    wk = DateSerial(y, m, 1)
    week = WeekDay(wk)
    
    For i = 0 To UBound(btnDay())
        If i < (week - 1) Or Month(wk) <> m Then
            btnDay(i).Label = "" & "~" & chr(13)
            btnDay(i).setVisible(False)
        Else
            btnDay(i).Label = Day(wk) & "~" & chr(13)
            btnDay(i).setVisible(True)
            If mdlHoliday.IsHoliday(wk) Then
                btnDay(i).getModel.TextColor = RGB(255,0,0)
            Else
                btnDay(i).getModel.TextColor = RGB(0, 0, 0)
            End If
            wk = wk + 1
        End If
    Next i
    
    scbMonth.setVisible(True)
    
End Sub

指定した日付に合わせてカレンダーのコントロールを調整します。OpenOffice.orgはマルチタスク(?)な処理をするので、時間のかかる処理をしている間でもコントロールの操作ができてしまいます。これでは色々問題が出てくるので、日付の表示を更新する間は年月用スクロールバーを非表示にして、年月を変更できないようにしてあります。

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

カレンダーダイアログ その1

ガントチャートでは、日付に関する操作が多くあります。休日の設定や工程の開始・終了日などをキーボードで入力しても可能ですが、それでは誤入力の原因になりやすくなります。また視覚的な操作感を向上させるために、カレンダーダイアログを作成し、それを用いることにします。ですが、いくつか前準備があるのでそちらを先に説明します。

休日を扱うために、休日用データシートを追加します。これは特に加工する必要は無く、名称を「休日」としておきます。休日シートは一つの列を1日、行を1月とします。
簡単に説明すると1月1日は「A1」、2月3日は「C2」となります。また、1年後の1月1日は「A13」です。これを実現するためには、工程を作成できる期間の先頭日を決定する必要があります。ここでは、ガントチャートforExcelの例を倣い、2000年1月1日を先頭日とします。
また、セルに入力するデータは平日が0で、休日を-1とします。

次に、休日の操作を簡便にするためのモジュールを作成し、名称を「mdlHoliday」とします。
そして、以下の変数を宣言します。

mdlHoliday

Public HolidaySheetName As String
Public HolidaySheet As Object

また、mdlMainに以下のコードを追加します。

mdlMain

Public FirstDate As Date
 
Public Sub Initialize
    
    '**中略***
    FirstDate = CDate("2000/1/1")
    HolidaySheetName = "休日"
    HolidaySheet = Sheets(HolidaySheetName)
    
End Sub

mdlHolidayには以下の関数を登録します。

  1. IsHolida関数 : 日付からそれが休日か否かを取得する。休日ならTrueを返します
  2. Change関数 : 日付を指定し、休日・平日を切り替えます
  3. getCell関数 : 目的の日付に相当するCellオブジェクトを返します
具体的なコードを以下に示します。

mdlHoliday

Public Function IsHoliday(TargetDate As Date) As Boolean
    
    IsHoliday = getCell(TargetDate).Value
    
End Function
 
Public Sub Change(TargetDate As Date)
    
    Dim oCell As Object
    
    oCell = getCell(TargetDate)
    oCell.Value = CBool(Not oCell.Value)
    
End Sub
 
Private Function getCell(TargetDate As Date) As Object
    
    Dim y As Integer
    Dim m As Integer
    Dim d As Integer
    
    y = Year(TargetDate) - Year(FirstDate)
    m = Month(TargetDate)
    d = Day(TargetDate)
    
    getCell = Cells(HolidaySheet, d, y * 12 + m)
    
End Function

前置きが長くなりましたが、次回からカレンダーダイアログを作成していきます。

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

項目編集ダイアログ その8

最後に設定用ボタンコントロールの動作を作成します。
これは、これまでに作成したgetValues関数にて、各コントロールの値を編集中のデータに割当て、編集フラグを真にしてダイアログを閉じるというものです。

mdlEditItem

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

長くなりましたが、以上で項目編集ダイアログの作成を終了します。

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

項目編集ダイアログ その7

工程の編集に関する部分の処理を解説します。
工程の編集には編集、追加、削除の3つがあり、それぞれbtnEditSchedule、btnAddSchedule、btnDelScheduleのボタン、lstScheduleに処理を割り当てています。

工程のリストボックスにて対象の工程を選択してから処理をするので、まず工程用のリストボックスを初期化する関数を作成します。

Private Sub Update_lstSchedule
    
    Dim i As Integer
    Dim j As Integer
    
    Redim Preserve ScheduleList(0)
    clearListBox(lstSchedule)
    
    j = 0
    For i = 1 To mdlSchedule.Count
        If Schedules(i)._ItemId = Id Then
            j = j + 1
            lstSchedule.AddItem(Schedules(i)._Name, _
                lstSchedule.getItemCount())
            Redim Preserve ScheduleList(j)
            ScheduleList(j) = Schedules(i)._Id
        End If
    Next i
    
End Sub

これは工程一覧用リストボックスを初期化し、編集中の項目に割り当てられた工程をリストボックスに追加し、それに合わせてID記録用の配列に工程のIDを登録しています。編集や追加、削除の操作をした後、この処理を毎回行う必要があるので関数化しておくと楽です。

次に編集処理を作成します。

Private Sub btnEditSchedule_actionPerformed
    
    Dim i As Integer
    i = lstSchedule.getSelectedItemPos + 1
    If i < 1 Then Exit Sub
    
    If mdlEditSchedule.Show(ScheduleList(i)) Then
        Update_lstSchedule
        flgUpdate = True
    End If
    
End Sub

これは、リストボックスから選択済みの工程IDを取得して工程編集用ダイアログを表示し、編集されればリストを更新して変更フラグを真とするという処理です。

次に追加処理を作成します。

Private Sub btnAddSchedule_actionPerformed
    
    Dim i As Integer
    i = mdlSchedule.Add(Id)
    mdlEditSchedule.Show(i)
    Update_lstSchedule
    flgUpdate = True
    
End Sub

工程を編集中の項目IDで初期化して追加します。そして追加した工程IDを使って工程編集用ダイアログを表示し、編集後リストを更新します。

最後に削除処理を作成します。

Private Sub btnDelSchedule_actionPerformed
    
    Dim i As Integer
    i = lstSchedule.getSelectedItemPos + 1
    If i < 1 Then Exit Sub
    
    mdlSchedule.Delete(ScheduleList(i))
    Update_lstSchedule
    flgUpdate = True
    
End Sub

これは、リストボックスから選択済みの工程IDを取得してその担当を削除し、リストを更新するという処理をします。

また、リストボックスのアクションリスナーを設定していますが、これはリストボックスをダブルクリックすると呼び出されるもので、基本的にbtnEditSchedule_actionPerformed関数を同じ動作です。なので、そのまま関数を呼び出してしまいます。

Private Sub lstSchedule_actionPerformed
    
    btnEditSchedule_actionPerformed
    
End Sub

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

項目編集ダイアログ その6

担当者の編集に関する部分の処理を解説します。
担当の編集には編集、追加、削除の3つがあり、それぞれbtnEditPerson、btnAddPerson、btnDelPersonのボタンに処理を割り当てています。

担当者のリストボックスにて対象の担当者を選択してから処理をするので、まず担当者用のリストボックスを初期化する関数を作成します。

Sub Update_lstPersonId
    Dim i As Integer
    i = lstPersonId.getSelectedItemPos
    mdlPerson.setListControl(lstPersonId)
    lstPersonId.SelectItemPos(i, True)
End Sub

これは担当一覧用リストボックスをリスト作成用関数で初期化し、選択済みの項目を選び直すというものです。編集や追加、削除の操作をした後、この処理を毎回行う必要があるので関数化しておくと楽です。

次に編集処理を作成します。

Private Sub btnEditPerson_actionPerformed
    
    Dim i As Integer
    i = lstPersonId.getSelectedItemPos + 1
    If i < 1 Then Exit Sub
    
    If mdlEditPerson.Show(i) Then
        Update_lstPersonId
        flgUpdate = True
    End If
    
End Sub

これは、リストボックスから選択済みの担当IDを取得して担当編集用ダイアログを表示し、編集されればリストを更新して変更フラグを真とするという処理です。

次に追加処理を作成します。

Private Sub btnAddPerson_actionPerformed
    
    Dim i As Integer
    i = mdlPerson.Add
    mdlEditPerson.Show(i)
    Update_lstPersonId
    flgUpdate = True
    
End Sub

担当者追加をして、追加した担当IDを使って担当編集用ダイアログを表示し、編集後リストを更新します。

最後に削除処理を作成します。

Private Sub btnDelPerson_actionPerformed
    
    Dim i As Integer
    i = lstPersonId.getSelectedItemPos + 1
    If i < 1 Then Exit Sub
    
    mdlPerson.Delete(i)
    Update_lstPersonId
    flgUpdate = True
    
End Sub

これは、リストボックスから選択済みの担当IDを取得してその担当を削除し、リストを更新するという処理をします。

担当のデータは編集中以外の項目データにも関連してくるので、mdlPersonできちんと編集用の関数を作成しておかないと処理がとても煩雑になってしまいます。

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

項目編集ダイアログ その5

配置したボタン類とリストボックスの動作を作成します。
これら全てのコントロールで同じアクションリスナーを利用するので、これまで同様にイベント発生元のコントロール名から処理を振り分ける処理を書きます。コードを示すと下記となります。

mdlEditItem

Private Sub dlgEditItemActionListener_actionPerformed(oEvent)
    Select Case oEvent.Source.getModel().Name
        Case "lstSchedule"
            lstSchedule_actionPerformed
        Case "btnEditPerson"
            btnEditPerson_actionPerformed
        Case "btnAddPerson"
            btnAddPerson_actionPerformed
        Case "btnDelPerson"
            btnDelPerson_actionPerformed
        Case "btnEditSchedule"
            btnEditSchedule_actionPerformed
        Case "btnAddSchedule"
            btnAddSchedule_actionPerformed
        Case "btnDelSchedule"
            btnDelSchedule_actionPerformed
        Case "btnOK"
            btnOK_actionPerformed
        Case Else
        
    End Select
End Sub
 
Private Sub dlgEditItemActionListener_disposing: End Sub

これだけの量になれば、これまで不必要に思われたこの書き方を納得して頂けるのではないでしょうか。
この書き方には多くのメリットがあり、ここでコントロールに動作を割り当てる別の設定方法と比較してその利点を示します。

IDEで各コントロールに直接動作を割り当てる方法
これが一番簡単であるように思われるかもしれませんが、これには欠点があります。それは、モジュールが違っても同じ名前の関数を割り当てることができないということです。いくつかのダイアログでbtnOKという名前を使っている関係上、btnOK_actionPerformed関数をいくつも作っていますが、これを各ダイアログのコントロールにそれぞれのモジュールにある関数を割り当てても、一番最初に書かれたbtnOK_actionPerformed関数が実行されてしまいます。
つまり、各ダイアログ毎に別々のコントロール名称を用いるか別々の関数名を用いなくてはなりません。
極少量のダイアログを使ったマクロならこれでいいかもしれませんが、10個を越えるダイアログにいくつものコントロールを配置したようなマクロを作成する時にはとても管理できなくなります。上記の方法であれば、アクションリスナーの名前だけ変えておけば、そのリスナー関数内で指定される処理はまず同じモジュール内の関数を優先してくれるので、このような名称の衝突がありません。
それぞれにリスナーを作成して割り当てる方法
リスナーを生成時に割り当てる名前を重複させる事はできないので、同じくダイアログやコントロールが増えればそれだけ名称を考えなくてはなりません。これにより、名称がとても複雑になり管理が難しくなることが予想されます。
また一つの処理のみを書きたいと思っていても、リスナーの持っている全ての動作を宣言しておかないとエラーになるので、必然的に書かなくてはならないコードが増えます。例えば、マウスリスナーでボタンを押した時のみの処理を書きたくても、離した時、カーソルが上に来た時、離れた時、終了時といった他の処理も書かなくてはならなくなります。

このことから、現在のOOoBasicの仕様ではこれまで利用してきた方法が一番簡単であると考えています。

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

データ削除「分類」

データの削除処理を簡便にするため、Delete関数を作ります。
ここで、考えないといけないのは分類データに関連付けられている項目データの扱いです。そこで、Swap関数から見直しと訂正を行い、その後Delete関数を作ってみます。まず、改造後のSwap関数を示します。

mdlItem

Public Sub Swap(Data1 As CategoryType, Data2 As CategoryType)
    
    Dim wk As CategoryType
    
    Copy(Data1, wk)
    Copy(Data2, Data1)
    Copy(wk, Data2)
    
    Dim i As Integer
    
    For i = 1 To mdlItem.Count
        If Items(i)._CategoryId = Data1._Id Then
            Items(i)._CategoryId = Data2._Id
        ElseIf Items(i)._CategoryId = Data2._Id Then
            Items(i)._CategoryId = Data1._Id
        End If
    Next i
    
End Sub

こうすると、Swap関数でデータを交換するのに合わせて項目データの関連付けも修正されます。

次に、Delete関数を示します。

mdlItem

Public Sub Delete(Id As Integer)
    
    Dim i As Integer
    
    For i = Id To mdlCategory.Count - 1
        Swap(Categories(i), Categories(i+1))
    Next i
    
    i = Count
    Redim Preserve Categories(i-1)
    
    Dim j As Integer
    
    j = 1
    Do
        If mdlItem.Count < j Then Exit Do
        
        If Items(j)._CategoryId = i Then
            mdlItem.Delete(j)
        Else
            j = j + 1
        End If
    Loop
    
End Sub

Swap関数で削除対象のデータを配列の一番最後に移動させ、配列数を一つ減らします。
その後、削除対象の分類データに割り当てられていた項目データを削除しています。

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

データ削除「担当」

データの削除処理を簡便にするため、Delete関数を作ります。
ここで、考えないといけないのは担当データに関連付けられている項目データの扱いです。そこで、Swap関数から見直しと訂正を行い、その後Delete関数を作ってみます。まず、改造後のSwap関数を示します。

mdlPerson

Public Sub Swap(Data1 As PersonType, Data2 As PersonType)
    
    Dim wk As PersonType
    
    Copy(Data1, wk)
    Copy(Data2, Data1)
    Copy(wk, Data2)
    
    Dim i As Integer
    
    For i = 1 To mdlItem.Count
        
        If Items(i)._PersonId = Data1._Id Then
            Items(i)._PersonId = Data2._Id
        ElseIf Items(i)._PersonId = Data2._Id Then
            Items(i)._PersonId = Data1._Id
        End If
        
    Next i
    
End Sub

こうすると、Swap関数でデータを交換するのに合わせて項目データの関連付けも修正されます。

次に、Delete関数を示します。

mdlPerson

Public Sub Delete(Id As Integer)
    
    Dim i As Integer
    
    For i = Id To Count - 1
        Swap(Persons(i), Persons(i+1))
    Next i
    
    i = Count
    Redim Preserve Persons(i-1)
    
    Dim j As Integer
    
    For j = 1 To mdlItem.Count
        
        If Items(j)._PersonId = i Then
            Items(j)._PersonId = 0
        End If
        
    Next j
    
End Sub

Swap関数で削除対象のデータを配列の一番最後に移動させ、配列数を一つ減らします。
その後、削除対象の担当データに割り当てられていた項目データの担当IDを0(担当無し)に設定しています。

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

データ削除「項目」

データの削除処理を簡便にするため、Delete関数を作ります。
ここで、考えないといけないのは項目データに関連付けられている工程データの扱いです。そこで、Swap関数から見直しと訂正を行い、その後Delete関数を作ってみます。まず、改造後のSwap関数を示します。

mdlItem

Public Sub Swap(Data1 As ItemType, Data2 As ItemType)
    
    Dim wk As ItemType
    
    Copy(Data1, wk)
    Copy(Data2, Data1)
    Copy(wk, Data2)
    
    Dim i As Integer
    
    For i = 1 To UBound(Schedules())
        If Schedules(i)._ItemId = Data1._Id Then
            Schedules(i)._ItemId = Data2._Id
        ElseIf Schedules(i)._ItemId = Data2._Id Then
            Schedules(i)._ItemId = Data1._Id
        End If
    Next i
    
End Sub

こうすると、Swap関数でデータを交換するのに合わせて工程データの関連付けも修正されます。

次に、Delete関数を示します。

mdlItem

Public Sub Delete(Id As Integer)
    
    Dim i As Integer
    
    For i = Id To Count - 1
        Swap(Items(i), Items(i+1))
    Next i
    
    i = Count
    Redim Preserve Items(i-1)
    
    Dim j As Integer
    
    j = 1
    Do
        If mdlSchedule.Count < j Then Exit Do
        
        If Schedules(j)._ItemId = i Then
            mdlSchedule.Delete(j)
        Else
            j = j + 1
        End If
    Loop
    
End Sub

Swap関数で削除対象のデータを配列の一番最後に移動させ、配列数を一つ減らします。
その後、削除対象の項目データに割り当てられていた工程データを削除していきます。

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

データ削除「工程」

データの削除処理を簡便にするため、Delete関数を作ります。

mdlSchedule

Public Sub Delete(Id As Integer)
    
    Dim i As Integer
    
    For i = Id To Count - 1
        Swap(Schedules(i), Schedules(i+1))
    Next i
    
    i = Count
    Redim Preserve Schedules(i-1)
    
End Sub

Swap関数で削除対象のデータを配列の一番最後に移動させ、配列数を一つ減らします。

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

データ追加「担当」

データの追加処理を簡便にするため、Add関数を作ります。また、ついでにデータの総数を取得する処理も簡便にするためのCount関数を作成します。

mdlPerson

Public NewPersonName As String
 
Private Function Count As Integer
    
    Count = UBound(Persons())
    
End Function

Public Function Add As Integer
    
    Dim i As Integer
    i = Count + 1
    
    Redim Preserve Persons(i)
    With Persons(i)
        ._Id = i
        ._Name = NewPersonName & i
    End With
    
    Add = i
    
End Function

Add関数内では新しく追加したデータに初期値を設定します。IDは連番なので、そのまま番号を入力しその他のパラメータは始めから入っている方がふさわしい値を入れます。
名称は新しい名称用の変数を宣言し、mdlMain.Initialize関数内で宣言しておく事とします。

mdlMainのInitialize関数に追記

NewPersonName = "新規担当"

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

データ追加「工程」

データの追加処理を簡便にするため、Add関数を作ります。また、ついでにデータの総数を取得する処理も簡便にするためのCount関数を作成します。

mdlSchedule

Public Function Count As Integer
    
    Count = UBound(Schedules())
    
End Function
 
Public Function Add(ItemId As Integer) As Integer
    
    Dim i As Integer
    i = Count + 1
    
    Redim Preserve Schedules(i)
    With Schedules(i)
        ._Id = i
        ._Name = NewScheduleName & i
        ._ItemId = ItemId
        ._PlanColor = -1
        ._ActColor = -1
        ._LineType = -1
        ._Weight = 1
    End With
    
    Add = i
    
End Function

Add関数内では新しく追加したデータに初期値を設定します。IDは連番なので、そのまま番号を入力しその他のパラメータは始めから入っている方がふさわしい値を入れます。
また、工程には項目のIDが必須となりますので、この関数を呼び出す時の引数に項目のIDを入れます。
名称は新しい名称用の変数を宣言し、mdlMain.Initialize関数内で宣言しておく事とします。

mdlMainのInitialize関数に追記

NewScheduleName = "新規工程"

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

データ追加「項目」

データの追加処理を簡便にするため、Add関数を作ります。また、ついでにデータの総数を取得する処理も簡便にするためのCount関数を作成します。

mdlItem

Public NewItemName As String
 
Public Function Count As Integer
    
    Count = UBound(Items())
    
End Function
 
Public Sub Add
    
    Dim i As Integer
    
    i = Count + 1
    
    Redim Preserve Items(i)
    With Items(i)
        ._Id = i
        ._Name = NewItemName & i
        ._CategoryId = mdlCategory.Count
    End With
    
End Sub

Add関数内では新しく追加したデータに初期値を設定します。IDは連番なので、そのまま番号を入力しその他のパラメータは始めから入っている方がふさわしい値を入れます。
名称は新しい名称用の変数を宣言し、mdlMain.Initialize関数内で宣言しておく事とします。

mdlMainのInitialize関数に追記

NewItemName = "新規項目"

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

データ追加「分類」

データの追加処理を簡便にするため、Add関数を作ります。また、ついでにデータの総数を取得する処理も簡便にするためのCount関数を作成します。

mdlCategory

Public NewCategoryName As String
 
Function Count As Integer
    
    Count = UBound(Categories())
    
End Function
 
Sub Add
    
    Dim i As Integer
    
    i = Count + 1
    
    Redim Preserve Categories(i)
    
    With Categories(i)
        ._Id = i
        ._Name = NewCategoryName
        ._Visible = True
    End With
    
End Sub

Add関数内では新しく追加したデータに初期値を設定します。IDは連番なので、そのまま番号を入力しその他のパラメータは始めから入っている方がふさわしい値を入れます。
名称は新しい名称用の変数を宣言し、mdlMain.Initialize関数内で宣言しておく事とします。

mdlMainのInitialize関数に追記

NewCategoryName = "新規分類"

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

教師のためのOpenOffice
教師のためのOpenOffice

"そこでこのサイトではOpenOffice.orgの中で主にCalc(表計算ドキュメント)を取り上げ、学校現場でよく使われるものを題材にして、その使い方を紹介していきます。"と書かれているように、中で紹介されるサンプルはほとんど学校で使うようなものです。

MSOfficeとOpenOffice.orgの比較から始まり、関数の使い方や各種具体的なシートの作成方法と続き、マクロの入門まで懇切丁寧に解説されています。

このサイトの作者もExcelをずいぶん使い込んでおられるようです。やっぱりある程度使い込んでいると、ExcelもCulcもあまり変わらないという印象を受けるのでしょう。MSOfficeからOpenOffice.orgに移行できるか否かは利用者の能力に依存する状態だということなのかなと思います。
同じ機能を持っていても初心者はアイコンの図柄や配置場所が変わるだけで使えなくなります。このサイトでも言われているのですが、解説書が少ない状況をなんとかするともっと普及するかなと僕も思います。

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

項目編集ダイアログ その4

進捗状況を変更すると、スクロールバーの左側にあるラベルコントロールに表示する数値を更新する機能を追加します。

まず、スクロールバーを調整した時に呼び出されるAdjustmentListenerを宣言し、スクロールバーに登録します。これは既に提示したマクロの中にありますが、必要な部分を再度書き出します。

mdlEditItem

'変数宣言
Private oAdjustmentListener As Object

Sub Initialize
    
    '~ 略 ~
    
    oAdjustmentListener = CreateUnoListener( _
        "dlgEditItemAdjustmentListener_", _
        "com.sun.star.awt.XAdjustmentListener")
    scbStatus.addAdjustmentListener(oAdjustmentListener)

    '~ 略 ~
    
End Sub

スクロールバーを調整した時に実行したい関数を宣言します。動作の内容はスクロールバーの値に「%」を付加してラベルコントロールtxtStatusに表示するというものです。

Private Sub scbStatus_Changed
    txtStatus.Text = scbStatus.Value & "%"
End Sub

最後に、AdjustmentListenerに必要な関数を宣言します。ここでも、今まで通り呼び出し元の名前から処理を分岐する内容になっています。

Private Sub dlgEditItemAdjustmentListener_adjustmentValueChanged(oEvent)
    
    Select Case oEvent.Source.getModel().Name
        Case "scbStatus"
            scbStatus_Changed
        Case Else
        
    End Select
    
End Sub

Private Sub dlgEditItemAdjustmentListener_disposing(): End Sub

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

項目編集ダイアログ その3

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

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

mdlEditSchedule

Private Sub setValues(obj As Object)
    
    txtId.Text = ControlLabelString(obj._Id)
    txtName.Text = obj._Name
    lstCategoryId.SelectItemPos(obj._CategoryId - 1, True)
    lstPersonId.SelectItemPos(obj._PersonId - 1, True)
    txtNote.Text = obj._Note
    chkComplete.State = Bool2State(obj._Complete)
    scbStatus.Value = obj._Status
    txtHyperlink.Text = obj._Hyperlink
    
    txtStatus.Text = scbStatus.Value & "%"
    
End Sub

Private Sub getValues
    
    With  Items(Id)
        ._Name = txtName.Text
        ._CategoryId = lstCategoryId.getSelectedItemPos + 1
        ._PersonId = lstPersonId.getSelectedItemPos + 1
        ._Note = txtNote.Text
        ._Complete = State2Bool(chkComplete)
        ._Status = scbStatus.Value
        ._Hyperlink = txtHyperlink.Text
    End With
    
End Sub

各関数の説明をします。

  1. Sub setValue(obj As Object)
    ScheduleTypeの変数を受け取ると、その値を各コントロールに配置していきます。
    分類と担当のリストは割り当てているデータを選択済みの状態にするため、SelectItemPosメソッドを使用します。このとき、IDは1から始まりますが、リストボックスは0から始まるので1を引いてから割り当てます。
    また、進捗状況の設定値をラベルコントロールに表示する命令を書きます。
  2. Sub getValues
    Show関数で受け取ったIDのデータに各コントロールの値を代入していきます。
    setValueと同様の理由から、リストボックスの選択値に1を足しています。

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

秋田パソコンステーション

マクロ&データベース.オープンオフィスby秋田パソコンステーション

オープンオフィスの基本的な使い方、マクロのサンプル、方式別のデータベース作成方法をWindowsを使って解説されています。また、見積書を作成するマクロを公開されています。

解説はどれも丁寧で、スクリーンショットを織り交ぜながら説明されており、初心者の方にもとてもわかりやすいと感じました。また、あまりOOoBasicの説明をしたサイトが少ない中で、データベースとの接続方法まで解説しているのはとても有益な情報を提供されていると言えます。

MSOfficeに関する記述が一切無いので、これからパソコンを始める人を対象にしておられるのかなと思いますが、これはなかなか良いアイディアですよね。初心者の方は、最初に触れ、覚えたOfficeアプリケーションを使うだろうから、そこでOpenOffice.orgに触ってもらえば普及率も上がる事でしょう。

余談ですが、近所の商工会議所ではWordPerfectを使ってパソコン講習を行っていたそうです...これはどうだかな。

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

項目編集ダイアログ その2

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


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

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

Option Explicit
 
Private oDialog As Object '---(1)
 
Private lblId As Object
Private lblName As Object
Private lblCategoryId As Object
Private lblPersonId As Object
Private lblNote As Object
Private lblStatus As Object
Private lblHyperlink As Object
Private lblSchedule As Object
 
Private txtId As Object
Private txtName As Object
Private lstCategoryId As Object
Private lstPersonId As Object
Private txtNote As Object
Private chkComplete As Object
Private txtStatus As Object
Private scbStatus As Object
Private txtHyperlink As Object
Private lstSchedule As Object
 
Private btnEditSchedule As Object
Private btnAddSchedule As Object
Private btnDelSchedule As Object
Private btnEditPerson As Object
Private btnAddPerson As Object
Private btnDelPerson As Object
Private btnOK As Object
 
Public dlgEditItem_Title As String '---(2)
Public dlgEditItem_lblId_Text As String
Public dlgEditItem_lblName_Text As String
Public dlgEditItem_lblCategoryId_Text As String
Public dlgEditItem_lblPersonId_Text As String
Public dlgEditItem_lblNote_Text As String
Public dlgEditItem_lblStatus_Text As String
Public dlgEditItem_lblHyperlink_Text As String
Public dlgEditItem_lblSchedule_Text As String
Public dlgEditItem_chkComplete_Label As String
Public dlgEditItem_btnEditSchedule_Label As String
Public dlgEditItem_btnAddSchedule_Label As String
Public dlgEditItem_btnDelSchedule_Label As String
Public dlgEditItem_btnEditPerson_Label As String
Public dlgEditItem_btnAddPerson_Label As String
Public dlgEditItem_btnDelPerson_Label As String
Public dlgEditItem_btnOK_Label As String
 
Private oActionListener As Object '---(3)
Private oAdjustmentListener As Object
 
Private Id As Integer '---(4)
Private flgUpdate As Boolean '---(5)
 
Private ScheduleList() As Integer '---(6)
 
Public Function Show(TargetId As Integer) As Boolean '---(7)
    
    flgUpdate = False
    
    Id = TargetId
    If Id < 1 Or mdlItem.Count < Id Then Exit Function
    
    Initialize
    setValues(Items(Id))
    With oDialog
        .execute
        .dispose
    End With
    
    Show = flgUpdate
    
End Function
 
Private Sub Initialize '---(8)
    
    oDialog = createUnoDialog(DialogLibraries.Standard.dlgEditItem)
    
    With oDialog
        .Title = dlgEditItem_Title
        lblId = .getControl("lblId")
        lblName = .getControl("lblName")
        lblCategoryId = .getControl("lblCategoryId")
        lblPersonId = .getControl("lblPersonId")
        lblNote = .getControl("lblNote")
        lblStatus = .getControl("lblStatus")
        lblHyperlink = .getControl("lblHyperlink")
        lblSchedule = .getControl("lblSchedule")
        
        txtId = .getControl("txtId")
        txtName = .getControl("txtName")
        lstCategoryId = .getControl("lstCategoryId")
        lstPersonId = .getControl("lstPersonId")
        txtNote = .getControl("txtNote")
        chkComplete = .getControl("chkComplete")
        scbStatus = .getControl("scbStatus")
        txtStatus = .getControl("txtStatus")
        txtHyperlink = .getControl("txtHyperlink")
        lstSchedule = .getControl("lstSchedule")
        
        btnEditSchedule = .getControl("btnEditSchedule")
        btnAddSchedule = .getControl("btnAddSchedule")
        btnDelSchedule = .getControl("btnDelSchedule")
        btnEditPerson = .getControl("btnEditPerson")
        btnAddPerson = .getControl("btnAddPerson")
        btnDelPerson = .getControl("btnDelPerson")
        btnOK = .getControl("btnOK")
    End With
    
    '---(9)
    oActionListener = CreateUnoListener("dlgEditItemActionListener_", _
        "com.sun.star.awt.XActionListener")
    oAdjustmentListener = _
        CreateUnoListener("dlgEditItemAdjustmentListener_", _
        "com.sun.star.awt.XAdjustmentListener")
    
    lblId.Text = dlgEditItem_lblId_Text
    lblName.Text = dlgEditItem_lblName_Text
    lblCategoryId.Text = dlgEditItem_lblCategoryId_Text
    lblPersonId.Text = dlgEditItem_lblPersonId_Text
    lblNote.Text = dlgEditItem_lblNote_Text
    lblStatus.Text = dlgEditItem_lblStatus_Text
    lblHyperlink.Text = dlgEditItem_lblHyperlink_Text
    lblSchedule.Text = dlgEditItem_lblSchedule_Text
    
    chkComplete.Label = dlgEditItem_chkComplete_Label
    
    'MsgBox scbStatus.Dbg_Methods
    scbStatus.addAdjustmentListener(oAdjustmentListener)
    
    lstSchedule.addActionListener(oActionListener)
    
    With btnEditSchedule
        .setLabel(dlgEditItem_btnEditSchedule_Label)
        .addActionListener(oActionListener)
    End With
    
    With btnAddSchedule
        .setLabel(dlgEditItem_btnAddSchedule_Label)
        .addActionListener(oActionListener)
    End With
    
    With btnDelSchedule
        .setLabel(dlgEditItem_btnDelSchedule_Label)
        .addActionListener(oActionListener)
    End With
    
    With btnEditPerson
        .setLabel(dlgEditItem_btnEditPerson_Label)
        .addActionListener(oActionListener)
    End With
    
    With btnAddPerson
        .setLabel(dlgEditItem_btnAddPerson_Label)
        .addActionListener(oActionListener)
    End With
    
    With btnDelPerson
        .setLabel(dlgEditItem_btnDelPerson_Label)
        .addActionListener(oActionListener)
    End With
    
    With btnOK
        .setLabel(dlgEditItem_btnOK_Label)
        .addActionListener(oActionListener)
    End With
    
    mdlCategory.setListControl(lstCategoryId) '---(10)
    mdlPerson.setListControl(lstPersonId)
    
    Update_lstSchedule '工程データ用リストボックスを初期化する(後日解説予定)
    
End Sub

各部の解説を行います

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

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

mdlMainのInitialize関数に追記

    dlgEditItem_Title = "項目編集"
    dlgEditItem_lblId_Text = ControlLabelString("ID")
    dlgEditItem_lblName_Text = ControlLabelString("名称")
    dlgEditItem_lblCategoryId_Text = ControlLabelString("分類")
    dlgEditItem_lblPersonId_Text = ControlLabelString("担当者")
    dlgEditItem_lblNote_Text = ControlLabelString("備考")
    dlgEditItem_lblStatus_Text = ControlLabelString("進捗状況")
    dlgEditItem_lblHyperlink_Text = ControlLabelString("ハイパーリンク")
    dlgEditItem_lblSchedule_Text = ControlLabelString("工程")
    dlgEditItem_chkComplete_Label = ControlLabelString("完了")
    dlgEditItem_btnEditSchedule_Label = ControlLabelString("編集")
    dlgEditItem_btnAddSchedule_Label = ControlLabelString("追加")
    dlgEditItem_btnDelSchedule_Label = ControlLabelString("削除")
    dlgEditItem_btnEditPerson_Label = ControlLabelString("編集")
    dlgEditItem_btnAddPerson_Label = ControlLabelString("追加")
    dlgEditItem_btnDelPerson_Label = ControlLabelString("削除")
    dlgEditItem_btnOK_Label = ControlLabelString("設定")

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

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

項目編集ダイアログ その1

項目は分類に割当られるものでありながら、工程や担当者を割り当てられるデータでガントチャートforOOoを構成するデータの中で一番複雑です。
そこで、項目編集ダイアログにはこれら全てのデータとの関係を編集できる機能が必要になってきます。

単純に以下の機能が必要です。

  1. 項目のデータを編集する
  2. 分類を選択する
  3. 担当を選択する
  4. 工程を追加、削除、変更する

2と3のデータを選択する機能を実現するために役立つのがリストボックスです。分類、担当、工程データをリストボックスに割り当てるという関数を作成します。そこで、それぞれのデータ用モジュールにsetListControl関数を追加します。但し、工程はちょっと特殊になるので別の方法で作成することとします。
追加するコードを下記に示します。

mdlCategory

Public Sub setListControl(oList As Object)
    Dim i As Integer
    clearListBox(oList)
    For i = 1 To Count
        oList.AddItem(Categories(i)._Name, oList.getItemCount())
    Next i
End Sub

mdlPerson

Public Sub setListControl(oList As Object)
    Dim i As Integer
    clearListBox(oList)
    For i = 1 To Count
        oList.AddItem(Persons(i)._Name, i)
    Next i
End Sub

oListはリストボックスのコントロールを割り当てた変数で、受け取った変数に割り当てられたリストボックスを初期化してデータをと登録してゆくというものです。
こうして作っておけば、今後これらのリストを他で使うような事があった場合に流用が容易になります。

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

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

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

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

mdlEditSchedule

Private Sub imgColor_mousePressed(oEvent)
    
    Dim imgModel As Object
    Dim s As String
    imgModel = oEvent.Source.getModel
    Select Case imgModel.Name
        Case "imgPlanColor"
            s = dlgEditSchedule_PlanColor
        Case "imgActColor"
            s = dlgEditSchedule_ActColor
    End Select
    
    imgModel.BackgroundColor = _
        mdlSelectColor.Show(s,imgModel.BackgroundColor)
    
End Sub
 
Private Sub btnOK_actionPerformed
    getValues
    flgUpdate = True
    oDialog.endExecute
End Sub
 
Private Sub dlgEditScheduleActionListener_actionPerformed(oEvent)
    Select Case oEvent.Source.getModel().Name
        Case "btnOK"
            btnOK_actionPerformed
        Case Else
        
    End Select
End Sub
 
Private Sub dlgEditScheduleActionListener_disposing: End Sub
 
Sub dlgEditScheduleMouseListener_mousePressed(oEvent As Object)
    Select Case oEvent.Source.getModel().Name
        Case "imgPlanColor", "imgActColor"
            imgColor_mousePressed(oEvent)
        Case Else
        
    End Select
End Sub
Sub dlgEditScheduleMouseListener_disposing(): End Sub
Sub dlgEditScheduleMouseListener_mouseReleased(oEvent): End Sub
Sub dlgEditScheduleMouseListener_mouseEntered(oEvent): End Sub
Sub dlgEditScheduleMouseListener_mouseExited(oEvent): End Sub

各関数の説明をします。

  1. Sub imgColor_mousePressed(oEvent)
    クリックされたコントロール名から予定か実績かを判断し、ダイアログに表示するタイトルを決め、色選択用ダイアログを表示する。ダイアログで色を選択したら、その色を設定します。
  2. Sub btnOK_actionPerformed
    コントロールの値をデータに記録し、データが変更されたことを認識するためのフラグをTrueにしてからダイアログを閉じます。
  3. Sub dlgEditCategoryActionListener_actionPerformed(oEvent As ActionEvent)
    引数のActionEventオブジェクトから実行元のコントロール名を取得し、各コントロール毎の処理に振り分けます。
  4. Sub dlgEditCategoryActionListener_disposing
    ダイアログを終了時、ActionListenerを破棄するタイミングで実行される関数ですがこのダイアログでは必要ないので空白のままとます。但し、ActionListenerは必ずこの関数を実行しようとしますので、空白のままでも宣言しておかないとエラーになります。
  5. Sub dlgEditScheduleMouseListener_mousePressed(oEvent As Object)
    マウスリスナーを割り当てたコントロールをクリックすると呼び出される関数です。コントロール名から処理を振り分けます。
  6. Sub dlgEditScheduleMouseListener_disposing()
    Sub dlgEditScheduleMouseListener_mouseReleased(oEvent)
    Sub dlgEditScheduleMouseListener_mouseEntered(oEvent)
    Sub dlgEditScheduleMouseListener_mouseExited(oEvent)
    マウス動作時の処理内容ですが、特に指定する内容が無くても作成しておかないとエラーになります。

以上で工程編集ダイアログの完成です。

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

mdlMain

Sub Test
    Initialize
    mdlSchedule.LoadAll
    If mdlEditSchedule.Show(1) Then mdlSchedule.SaveAll
End Sub

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

COPYRIGHT(C) 2004 POWERD BY FC2 ALLRIGHT RESERVED.
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。