2025/11/03

Notes - Excel 連携:#59)ビューをそのまま Excel へ ④ - 出力順序調整と行タイプの判定

ビューをビューっぽく Excel に出力する方法の 4 回目です。今回の挑戦では、ビューのカテゴリを Excel のグループを使って表現します。グループを使うには、合計行を明細の下に配置する必要があります。ビューと位置が逆転するので、出力順序の調整行います。


出力順序の調整の仕様

まずは仕様を整理するため、手順を図式化します。

ビューから 1 行ずつ順に読み込み、順次処理します。読み込んだ行のタイプに応じて処理が分かれます。

行タイプ 処理
カテゴリ 明細行の出力後に出力します。
複数のカテゴリを出力する場合には、下位のカテゴリから順に出力します。
明細行(文書) 読み込んだ順にそのまま出力します。
合計行 ビューの最後の行。
出力していないカテゴリがあれば出力してから、合計行を出力します。


行タイプの判定

ビューから読み込んだデータの行のタイプは、NotesViewEntry のプロパティで判定できます。IsCategory が True の場合はカテゴリ行、IsTotal が True の場合は合計行となります。それ以外は明細行となります(IsDocument プロパティを使用しても OK です)。


カテゴリレベルの取得

カテゴリ行の処理ではカテゴリレベルを知る必要があります。これは、カテゴリ列の値で判定できそうです。下図は ColumnValues の値をそのまま Excel に表示したときの画面ですが、サブカテゴリでは上位カテゴリの列には値が入らないことを利用します。

カテゴリ行の ColumnValues 値からカテゴリのレベルを取得する関数は次の通りです。

%REM
カテゴリ列の階層を返す

◆ 引数
vvLine        Variant    カテゴリ列のカラムデータ
vvCtgColNo Variant    カテゴリ列番号のリスト(ない場合最初の要素が0)

◆ データ型(戻り値)  Integer
カテゴリレベル(最上位カテゴリ = 1)
%END REM

Function xGetCategoryLv(vvLine As Variant, vvCtgCol As Variant) As Integer
   Dim i As Integer

   'カテゴリ列がない場合はキャンセル
   If vvCtgCol(0) = 0 Then Exit Function

   '上位カテゴリから順にチェック
   For i = 0 To UBound(vvCtgCol)
      '値が入っている列が階層
      If CStr(vvLine(vvCtgCol(i)-1)) <> "" Then
         xGetCategoryLv = i + 1
         Exit Function
      End If
   Next
End Function


メインルーチンの修正

それでは、今回整理した手順に従い出力順序を調整するように修正します。まずは、前回紹介した xPrintAllData 関数に追加します。大きく変更されていますが、薄い色の部分は変更のない箇所です。

%REM
ビューの全データを Excel シートに出力

◆ 引数
voSheet          Variant          Excel シート
vnvExport      NotesView   出力するビュー
vvCtgColNo   Variant         カテゴリ列番号のリスト(ない場合最初の要素が0)
vvCtgColor    Variant          カテゴリ列の文字色のリスト(要素数はrvCtgColNoと同じ)

◆ データ型(戻り値)  Integer
次の出力行番号(最終出力行 + 1)
%END REM

Function xPrintAllData(voSheet As Variant, vnvExport As NotesView, vvCtgColNo As Variant, vvCtgColor As Variant) As Integer
   Dim nvnav As NotesViewNavigator
   Dim nve As NotesViewEntry


   'カテゴリを含むビューの情報を取得
   Set nvnav = vnvExport.CreateViewNav()

   'スタックエリア用変数

   Dim avStack_Value() As Variant    'カテゴリ行の全カラムデータ

   Dim iRow As Integer
   Dim vLine As Variant

   Dim iLv_New As Integer    '読み込んだカテゴリレベル
   Dim iLv_Cur As Integer      '処理中のカテゴリレベル

   'スタックエリア確保(カテゴリ数と同じ)
   ReDim avStack_Value(UBound(vvCtgColNo))

   'ビューの出力開始
   iRow = 2     'シートの 2 行目から出力
   iLv_Cur = 0    'カテゴリレベル

   'ビューの 1 行目を取得
   Set nve = nvnav.GetFirst()

   'ビューのデータがなくなるまでループ
   Do Until (nve Is Nothing)
      '現在のビュー行の全カラム値を取得
      vLine = nve.ColumnValues

      '行タイプに応じた処理
      If nve.IsTotal Then
         '合計行(=最終行)
         '未出力のカテゴリがあれば出力

         iRow = xPrintLine_Category(voSheet, iRow, 1, iLv_Cur, avStack_Value, vvCtgColNo, vvCtgColor)
         iLv_Cur = 0    'スタックのカテゴリはない

         '合計出力
         voSheet.Rows(iRow).Interior.Color = RGB(238, 238, 238)    '背景は薄いグレー
         iRow = xPrintLine(voSheet, iRow, vLine)
      ElseIf nve.IsCategory Then
         'カテゴリ列
         '読み込んだカテゴリレベル取得

         iLv_New = xGetCategoryLv(vLine, vvCtgColNo)

         'スタックのカテゴリの処理
         If iLv_New <= iLv_Cur Then
            '読み込んだカテゴリは現在と同じか上位のカテゴリ
            '読み込んだカテゴリまでを出力

            iRow = xPrintLine_Category(voSheet, iRow, iLv_New, iLv_Cur, avStack_Value, vvCtgColNo, vvCtgColor)
         End If

         '読み込んだカテゴリをセット
         avStack_Value(iLv_New - 1) = vLine     'カテゴリをスタックに記録
         iLv_Cur = iLv_New '読み込んだカテゴリレベルを記憶
      Else
         '明細行(= 文書)
         iRow = xPrintLine(voSheet, iRow, vLine)
      End If

      'ビューの次の行を取得
      Set nve = nvnav.GetNext(nve)
   Loop

   '残りのカテゴリがあれば出力(= 合計のないビュー用)
   If iLv_Cur > 0 Then
      iRow = xPrintLine_Category(voSheet, iRow, 1, iLv_Cur, avStack_Value, vvCtgColNo, vvCtgColor)
   End If

   xPrintAllData = iRow
End Function

出力順の調整で重要な変数は avStack_Value です。定義されているカテゴリ数分の要素を持つの配列となっており、現在処理中のカテゴリ行の全カラムデータを保持します。明細行出力後はここからカテゴリのデータを取得して出力するということですね。なお、全カラムデータ自身が配列であるため、avStack_Value は Variant 型の配列となっています。

カテゴリの情報は上位のカテゴリから順にセットされ、下位から順に出力されます。このような動作から変数名に ”Stack” と付けています。


サンプルのビューではカテゴリ列は 2 つですが、ビューによって階層数はさまざまです。カテゴリがないこともあります。また、合計行がない場合も考えられます。どのようなビューにも対応できるよう、合計行の処理とループを抜けたあとに、出力されていないカテゴリの処理を行っている点もポイントです。


カテゴリ行の出力

最後に、カテゴリを Excel シートに出力する関数の紹介です。

引数の viMin と viMax で出力するカテゴリレベルを受け取ります。その範囲で出力するのですが、下位の階層から出力させるため For ループの Step が -1 となっています。

%REM
カテゴリ行を Excel シートに出力

◆ 引数
voSheet    Variant   Excel シート
viRow        Integer   出力行(シートの行番号)
viMin          Integer   出力するカテゴリレベル(上位)
viMax         Integer   出力するカテゴリレベル(下位)
vvStack_Value    Variant    カテゴリ行の値(配列、1要素が1行分の値(配列)を保持)
vvCtgColNo    Variant   カテゴリ列番号のリスト(配列)
vvCtgColor     Variant   カテゴリ列の文字色のリスト(配列)
 
◆ データ型(戻り値)  Integer
次の出力行番号
 
◆ 使い方
viMin ~ viMax 間のカテゴリを出力します。
下位カテゴリである viMax から順に出力します。
%END REM

Function xPrintLine_Category(voSheet As Variant, ByVal viRow As Integer, ByVal viMin As Integer, ByVal viMax As Integer, vvStack_Value As Variant, vvCtgColNo As Variant, vvCtgColor As Variant) As Integer
   Dim iRow As Integer
   Dim i As Integer
   Dim j As Integer
   Dim oRange As Variant

   iRow = viRow

   'カテゴリがあれば出力
   For i = viMax To viMin Step -1
      'カテゴリ行の背景
      voSheet.Rows(iRow).Interior.Color = RGB(238, 238, 238)    '薄いグレー

      'カテゴリ列の文字色
      For j = 0 To UBound(vvCtgColNo)
         voSheet.Cells(iRow, vvCtgColNo(j)).Font.Color = vvCtgColor(j)
      Next

      '保存していたカテゴリ行を出力
      iRow = xPrintLine(voSheet, iRow, vvStack_Value(i-1))
   Next

   xPrintLine_Category = iRow
End Function

Excel シートへの出力は 前回(#58)作成した xPrintLine 関数で行っているのですが、カテゴリ行の専用の装飾である背景の設定とカテゴリ列の文字色の設定はこの関数内で行っています。#57 で取得したカテゴリ列の位置(vvCtgColNo)と色(vvCtgColor)をやっと使いましたね。


動作確認と次回の予定

ここまでできたら実行して結果を確認します。カテゴリ列がうまく明細の下に、下位から順に表示されていれば、成功です。

次回は最後の仕上げとして、Excel のグループ機能を設定します。


前回 Notes - Excel 連携


0 件のコメント:

コメントを投稿