ラブびあ

ビール。ときどきラブ

rpxテキストを読み込んで動的にレイアウト

ActiveReportsを使ったVB6プロジェクトで、ユーザーごとに、ちょこっとだけレイアウトを変えたいときにお手軽に対応する方法

ActiveReportは、rpxというXML形式のレイアウト定義を読み書きできるので、ちょこっと変えたレイアウト(dsrとdsx)からrpxをそれぞれ作り、実行時にはこれを読み込んでレイアウトを変更するというやり方です。rpxファイルを配布したくなかったので、データベースから読み込むことにしました。rpxファイルはUTF-8、データベースから読み込んだ文字列(VB6内)はUTF-16LEなので、UTF16ToUTF8関数も作りました。

ユーザーごとのレイアウト定義を用意します。

UserReport.dsr
UserReport.dsx
UserReport.rpx

前記事の rpxファイルをDBへインポートする で UserReport.rpx をDBにインポートしておきます。アプリ実行時には、これを読み込んでLoadLayoutします。

呼び出し

    Dim obj As UserReport
    Set obj = New UserReport
    Call LoadLayout(obj, "UserReport.rpx")

共通関数

Declare Function WideCharToMultiByte Lib "kernel32" _
   (ByVal CodePage As Long, _
    ByVal dwFlags As Long, _
    ByVal lpWideCharStr As Long, _
    ByVal cchWideChar As Long, _
    ByRef lpMultiByteStr As Any, _
    ByVal cchMultiByte As Long, _
    ByVal lpDefaultChar As String, _
    ByVal lpUsedDefaultChar As Long) As Long

Public Sub LoadLayout(ByRef obj As ActiveReport, ReportID As String)
    Dim SQL         As String
    Dim OraDynaset  As OraDynaset
    Dim arr()       As String
    Dim rpx()       As Byte
    Dim i           As Long

    'バインドパラメータ設定
    With OraDataBase.Parameters
        For i = .Count - 1 To 0 Step - 1
            .Remove i
        Next
        .Add "ReportID", "", ORAPARM_INPUT, ORATYPE_VARCHAR2
        .Item("ReportID").Value = UCase(ReportID)
    End With
    
    SQL = "SELECT LINE FROM ActiveReports WHERE ReportID = :ReportID ORDER BY LINE_NO"
    Set OraDynaset = OraDataBase.CreateDynaset(SQL, ORADYN_READONLY)
    With OraDynaset
        If Not .EOF Then
            'データベースからrpxテキストをarrに読み込み
            ReDim arr(1 To .RecordCount)
            Do While Not .EOF
                arr(.RowPosition) = .Fields("LINE").Value & vbCrLf '行末に改行を付加
                .MoveNext
            Loop

            rpx = UTF16ToUTF8(Join(arr, ""))

            Call obj.LoadLayout(rpx)
        End If
    End With
End Sub

Public Function UTF16ToUTF8(UTF16 As String) As Byte()
    Const CP_UTF8 = 65001
    UTF16ToUTF8 = UnicodeToMultiByte(UTF16, CP_UTF8)
End Function

Public Function UnicodeToMultiByte(UTF16 As String, CodePage As Long) As Byte()
    Dim pInput As Long
    Dim pOutput As Long
    Dim size As Long
    Dim buf() As Byte

    'バッファサイズを取得するために、空変換してサイズだけ取得する
    pInput = StrPtr(UTF16)
    size = WideCharToMultiByte(CodePage, 0, pInput, -1, 0&, 0&, ByVal 0&, ByVal 0&)
    
    'バッファを確保してCodePageに変換する
    ReDim buf(size - 1)
    pOutput = VarPtr(buf(0))
    size = WideCharToMultiByte(CodePage, 0, pInput, -1, pOutput, size, ByVal 0&, ByVal 0&)
    
    '末尾のnullを除去する
    ReDim Preserve buf(size - 2)
    UnicodeToMultiByte = buf
End Function