Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

SPREAD for .NET Web Forms Ed.の表現力で魅力あるWebアプリケーションを作成する

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2009/10/26 14:00

ダウンロード サンプルソース (2.7 MB)

 SPREAD for .NET Web Forms Ed.は、Windowsアプリ用の定番表計算コンポーネントであるSPREADのWebアプリケーション版です。このSPREADを使ってTwitter関連のWebアプリケーションを作成していきながら、その魅力に迫っていきましょう。

より進化した定番コンポーネント SPREAD

 SPREAD for .NET Web Forms Ed.は、Windowsアプリケーション用の定番表計算コンポーネントであるSPREADのWebアプリケーション版です。

 今回、このコンポーネントを評価するにあたり、過去の苦い経験が蘇りました。それは、SPREAD for .NET 2.5J Web Forms Ed.が発売されたときのことです。ちょうど大規模なインターネット向けWebアプリケーションの案件があったので、SPREADの利用を前提に提案書を作成して受注しました。しかし、実際に提供するのに先立ち、トライアル版をダウンロードして試してみると、2.5JではFirefox対応が不十分で「Internet ExplorerとFirefox両方に対応して欲しい」というお客様の要望を満たせず、動作速度も遅いという状況でした。そのため、SPREADを前提に作成した提案書のデザインを見ながら、.NETの標準コンポーネントであるRepeaterコントロールとHTML/CSSを駆使して、なんとか完成にこぎつけました。

 そんなマイナスイメージがあったSPREAD for .NET Web Forms Ed.ですが、最新バージョンである3.0Jは、2.5Jとはまったく別物でした。3.0Jを試してみると、一部制限はありますがFirefox 2.0にも対応しており、基本的な見た目や操作は問題ありませんでした。また、2.5Jよりも明らかに動作が軽く、満足のいく動作速度が確保でき、「あのとき3.0Jがあれば、あんな苦労はしないで済んだし、もっと多機能でよいデザインの一覧表が搭載できたのに」と、とても複雑な気持ちになりました。チャンスがあれば、3.0Jで作り直したいくらいです。

 2.5Jを使ったことのある方も、3.0Jで初めてSPREAD for .NET Web Forms Ed.に触れる方も、ぜひこの機会に手にとって試してみることをお勧めします(トライアル版申し込みページ)。それでは早速、このSPREADを使ってTwitter関連のWebアプリケーションを作成していきながら、その魅力に迫っていきましょう。

SPREAD for .NET Web Forms Ed.利用前の準備

ツールバーにSPREAD for .NET Web Forms Ed.を追加する

 SPREAD for .NETをインストールした直後は、Visual Studioのツールボックスにコンポーネントが表示されていません。ツールボックスを右クリックして[アイテムの選択]メニューを選び、表示される画面で「FarPoint.Web.SpreadJ」名前空間の「FpSpread」を選択します。これでツールボックスにFpSpreadが表示されます。

図1 FarPoint.Web.SpreadJの追加
図1 FarPoint.Web.SpreadJの追加

「fp_client」フォルダの設置

 SPREAD for .NETが使用するアイコンやスクリプトは、「fp_client」フォルダの中に定義されています。そのため製品に同封されている「fp_client」フォルダを、開発環境のプロジェクトファイルや運用環境に配布しなければなりません。テストのしやすさを考えると、【図2】のようにプロジェクトファイルのルートに配置し、運用環境への配布もプロジェクトファイルの一部として行うのが簡単です。

図2 fp_clinetフォルダの配置
図2 fp_clinetフォルダの配置

データセットの内容を簡単に表示する

 SPREAD for .NETは多機能であると同時に、簡単に使えるモードも完備しています。例えば、DataSetの内容を一覧表示するのであれば、サンプルソースの「CZ0910FollowerType1」(リスト1)のようなコードだけで、【図3】の実行結果が得られます。

リスト1 Follower_Form.vb
Partial Class _Default
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, _
                            ByVal e As System.EventArgs) Handles Me.Load
        If Not Me.IsPostBack Then
            FpSpread1.ActiveSheetView.OperationMode = _
                                        FarPoint.Web.Spread.OperationMode.ReadOnly
            Me.FpSpread1.Width = Unit.Percentage(90)
        End If
    End Sub

    Protected Sub Get_Command_Click(ByVal sender As Object, _
                                    ByVal e As System.EventArgs) Handles Get_Command.Click
        Call SetData(Me.UserID_TextBox.Text, Me.Password_TextBox.Text)
    End Sub

    Private Sub SetData(ByVal userID As String, ByVal password As String)
        Using _proc As New Twitter
            Me.FpSpread1.ActiveSheetView.DataSource = _proc.GetFollowers(userID, password)
        End Using
    End Sub
End Class
  1. LoadイベントでPostback以外のときにOperationModeをReadOnlyにし、読み取り専用にして、Widthを90%に設定する
  2. [Get]ボタンをクリックしたらDataTableを取得してDataSourceに設定し、その内容を表示する
図3 サンプルソース「CZ0910FollowerType1」の実行結果
図3 サンプルソース「CZ0910FollowerType1」の実行結果

 このサンプルソースのDataSetの内容は、前回のSPREAD for .NET Windows Forms Ed.のサンプルと同様、コミュニケーションサービス「Twitter」上で、自分の発言を購読してくれている人の一覧になっています。

表示内容を修飾する

 「CZ0910FollowerType1」は、必要最小限のプロパティ設定とコード記述でSPREADを使うことを第一目的としているため、見た目の美しさは考慮していません。また、byte配列に格納している画像ファイルも表示されていません。

 サンプルソースに同梱してある「CZ0910FollowerType2」では、画面の修飾と画像ファイルの表示に対応したいと思います。

図4 サンプルCZ0910FollowerType2の実行結果
図4 サンプルCZ0910FollowerType2の実行結果

 「CZ0910FollowerType2」では、ページのLoadイベントとOnPreRenderメソッドの2カ所で修飾を行っています。大半の処理はLoadイベントに記載していますが、OnPreRenderメソッドでは数式の設定と画像表示を行っています。

Loadイベントでの処理

 Loadイベントでは、次の処理を行っています。

  1. スキンを適用
  2. スタイル設定用CSSを自動生成
  3. 文字の折り返しを禁止
  4. 列数設定
  5. 数式指定モードの指定
  6. シート全体の調整
  7. 列ヘッダの連結
  8. 高さや幅変更の抑止
  9. 各列の定義

スキンを適用

 SPREAD for .NETには、罫線や色調を組み合わせた「スキン」と呼ばれるテンプレート機能があります。独自にスキンを作成して指定する事もできますが、標準で定義されているデフォルトスキンにも使いやすいものが揃っています。

リスト2 スキンを適用
Me.FpSpread1.ActiveSheetView.ActiveSkin = FarPoint.Web.Spread.DefaultSkins.Colorful4

スタイル設定用CSSを自動生成

 BackColor、ForeColor、FontなどのスタイルをHTML化(レンダリング)するときに、CSSを自動生成して使うように指定すると、同じスタイルをCSS定義にまとめることができるためページサイズが小さくなりページロード時間が短くなります。

リスト3 スタイル設定用CSSを自動生成
Me.FpSpread1.RenderCSSClass = True

文字の折り返しを禁止

 テキスト型セルでは、セル内での文字折り返しを禁止するように設定します。そのための指定は、列やセルに直接行うのではなく、テキスト型セルのオブジェクトを生成し、AllowWrapプロパティにFalseを設定してからセルや列に割り当てます。

リスト4 文字の折り返しを禁止
Dim textCellType As New FarPoint.Web.Spread.TextCellType

     :

textCellType.AllowWrap = False

     :

Me.FpSpread1.ActiveSheetView.Columns(3).CellType = textCellType

列数の設定

 シート全体の調整などを行った場合、不要な列があると処理量が多くなるため、なるべく早いタイミングで列数を設定します。

リスト5 列数の設定
Me.FpSpread1.ActiveSheetView.Columns.Count = 9

数式指定モードを指定

 セルに数式を埋め込む場合、他のセルを値として指定する書式には「A1形式」と「R1C1形式」の2つがあります。R1C1形式の方が、列や行の位置を絶対位置でも相対位置でも指定しやすいので、サンプルではR1C1形式を指定しています。

リスト6 数式指定モードを指定
Me.FpSpread1.ActiveSheetView.ReferenceStyle = FarPoint.Web.Spread.Model.ReferenceStyle.R1C1

シート全体の調整

 サンプル「CZ0910FollowerType1」ではDataSetの内容に応じてセル型や列幅が自動的に決まりましたが、明示的に修飾を行うときにはこの自動機能をオフにしないと、設定した内容が実行時に有効になりません。

リスト7 シート全体の調整
Me.FpSpread1.ActiveSheetView.DataAutoCellTypes = False
Me.FpSpread1.ActiveSheetView.AutoGenerateColumns = False
Me.FpSpread1.ActiveSheetView.DefaultStyle.VerticalAlign = VerticalAlign.Middle
Me.FpSpread1.ActiveSheetView.AllowUserFormulas = False
  1. DataAutoCellTypesプロパティをFalseにして、セル型自動設定を無効化
  2. AutoGenerateColumnsプロパティをFalseにして、DataSetの列から自動的に列を生成しないように設定
  3. VerticalAlignプロパティをMiddleにして、セル高の真ん中に配置
  4. AllowUserFormulasプロパティをFalseにして、実行時に画面から数式の入力ができないように設定

列ヘッダの連結

 サンプル「CZ0909FollowerType2」では、左から2つ目の列ヘッダ(列指定は「0」から始まるので指定値は「1」)から3列を1つのヘッダに連結するデザインになっています。

 列ヘッダの連結には、AddColumnHeaderSpanCellメソッドを使用します。

リスト8 列ヘッダの連結
Me.FpSpread1.ActiveSheetView.ColumnHeaderSpanModel.Add(0, 1, 1, 3)

高さや幅変更の抑止

 Webアプリケーションにおいて、行の高さや列の幅を利用者が好みに応じて変更できるようにすることは難しい場合もありますが、SPREADではデフォルトで高さや幅の変更が可能な状態になっています。しかし、業務アプリケーションでは固定化して設計時の状態から変更しないことで、使い勝手の相違が生じないようにする場合があります。そのような場合は、ResizableプロパティをFalseにするとよいでしょう。

リスト9 高さや幅変更の抑止
Me.FpSpread1.ActiveSheetView.RowHeader.Rows.Default.Resizable = False
Me.FpSpread1.ActiveSheetView.ColumnHeader.Columns.Default.Resizable = False

各列の定義

 ここまで設定できたら、後は各列を順次定義していくだけになります。

リスト10 各列の定義
'ID列は非表示にする
Me.FpSpread1.ActiveSheetView.Columns(0).DataField = "ID"
Me.FpSpread1.ActiveSheetView.Columns(0).Visible = False
'アイコン列の設定を行う
Me.FpSpread1.ActiveSheetView.ColumnHeader.Cells(0, 1).Text = "ユーザ名"
Me.FpSpread1.ActiveSheetView.Columns(1).CellType = imageCellType
'名前列の設定を行う
Me.FpSpread1.ActiveSheetView.Columns(2).DataField = "Name"
Me.FpSpread1.ActiveSheetView.Columns(2).CellType = textCellType
Me.FpSpread1.ActiveSheetView.Columns(2).Locked = True
'ID名列の設定を行う
Me.FpSpread1.ActiveSheetView.Columns(3).DataField = "ScreenName"
Me.FpSpread1.ActiveSheetView.Columns(3).CellType = textCellType
Me.FpSpread1.ActiveSheetView.Columns(3).Locked = True
'プロテクション列は非表示にする
Me.FpSpread1.ActiveSheetView.Columns(4).DataField = "IsProtected"
Me.FpSpread1.ActiveSheetView.Columns(4).Visible = False
'プロテクションだったら○表示する列に計算式を設定する
Me.FpSpread1.ActiveSheetView.ColumnHeader.Cells(0, 5).Text = "プロテクト"
Me.FpSpread1.ActiveSheetView.Columns(5).CellType = textCellType
Me.FpSpread1.ActiveSheetView.Columns(5).Locked = True
Me.FpSpread1.ActiveSheetView.Columns(5).HorizontalAlign = HorizontalAlign.Center
Me.FpSpread1.ActiveSheetView.Columns(5).Formula = "IF(RC5=""True"",""○"","""")"
'フォロー列は非表示にする
Me.FpSpread1.ActiveSheetView.Columns(6).DataField = "IsFollowing"
Me.FpSpread1.ActiveSheetView.Columns(6).Visible = False
'フォローしてたら○表示する列に計算式を設定する
Me.FpSpread1.ActiveSheetView.ColumnHeader.Cells(0, 7).Text = "フォロー済"
Me.FpSpread1.ActiveSheetView.Columns(7).CellType = textCellType
Me.FpSpread1.ActiveSheetView.Columns(7).Locked = True
Me.FpSpread1.ActiveSheetView.Columns(7).HorizontalAlign = HorizontalAlign.Center
Me.FpSpread1.ActiveSheetView.Columns(7).Formula = "IF(RC[-1]=""True"",""○"","""")"
'最新の発言列の設定を行う
Me.FpSpread1.ActiveSheetView.Columns(8).DataField = "StatusText"
Me.FpSpread1.ActiveSheetView.ColumnHeader.Cells(0, 8).Text = "最新の発言"
Me.FpSpread1.ActiveSheetView.Columns(8).CellType = textCellType
Me.FpSpread1.ActiveSheetView.Columns(8).Locked = True
  1. データを特定するためのID列は、ユーザーインターフェイスとしては不要なので、VisibleプロパティにFalseを指定
  2. DataSetのIsProtected項目はそのまま表示しないので、VisibleプロパティにFalseを指定
  3. (3)の列を参照して、内容がTrueの時には「○」を表示するようにFomulaプロパティに指定。Fomulaプロパティに記述されている「RC5」指定は、同一行の5カラム目(指定値は「0」から始まるのでColumns.Get(4)列のこと)を表しています
  4. IsFollowing項目の内容がTrueの時には「○」を表示するようにFomulaプロパティを設定では、今までと異なる指定方法「RC[-1]」を採用。これは該当列の1つ前の列を表しています

OnPreRenderメソッドでの処理

 OnPreRenderメソッドは、イベントの処理がすべて終わってから呼び出されるサブプロシージャで、ここに図形の描画を設定することで、一覧作成後に常に画像処理が行えます。

リスト11 OnPreRenderメソッドでの処理
Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
    '数式の再計算を行います。
    Me.FpSpread1.ActiveSheetView.Recalculate()
    '画像を表示します
    Call SetImage()
    MyBase.OnPreRender(e)
End Sub

Private Sub SetImage()
    Dim ds As DataSet = CType(Me.FpSpread1.ActiveSheetView.DataSource, DataSet)

    With Me.FpSpread1.ActiveSheetView
        If ds IsNot Nothing Then
            For rowIndex As Integer = .TopRow To .TopRow + .PageSize - 1
                If rowIndex > .RowCount - 1 Then
                    Exit For
                End If
                .Cells(rowIndex, 1).CellType = CreateImageFile(ds.Tables(0).Rows(rowIndex))
            Next
        End If
    End With
End Sub

Private Function CreateImageFile(ByVal row As DataRow) As FarPoint.Web.Spread.ImageCellType
    Dim img As Byte() = CType(row.Item("ProfileImage"), Byte())
    Dim fileName As String = row.Item("ID").ToString
    Dim imgfileLogPath As String = "image\" & fileName & ".jpg"
    Dim imgFilePhyPath As String = System.IO.Path.Combine(Server.MapPath("."), imgfileLogPath)

    Using imgfile As New System.IO.FileStream(imgFilePhyPath, IO.FileMode.Create)
        imgfile.Write(img, 0, img.Length)
        imgfile.Close()
    End Using
    Return New FarPoint.Web.Spread.ImageCellType(imgfileLogPath)
End Function
  1. OnPreRenderメソッドからSetImageプロシージャを呼び出し、継承元のOnPreRenderメソッドを呼び出して、本来のPreRender処理を継続します。
  2. SetImageプロシージャでは、TopRowプロパティとPageSizeプロパティを使って、現在表示している行に対してbyte配列に格納されている画像ファイルを表示します。
  3. byte配列から直接画像を表示する機能はないので、CreateImageFile関数でbyte配列の内容をサーバ側のimageフォルダに出力し、そのファイル名をセルに渡します。
補足

 今回のサンプルはbyte配列からの出力例としたかったため、Twitterから取得した画像ファイルのURLから画像データを取り出し、それをbyte配列に格納して利用しています。しかし、画像ファイルのURLが分かっているのであれば、CreateImageFile関数は次のようなコードで十分です。

リスト12 Twitterのアイコン処理を前提とした最適化
Private Function CreateImageFile(ByVal row As DataRow) As FarPoint.Web.Spread.ImageCellType
    Return New FarPoint.Web.Spread.ImageCellType(row.Item("ProfileImageUrl").ToString)
End Function

デザイナを使ってデザインする

 サンプル「CZ0910FollowerType2」でコードを明記して指定したデザインは、SPREAD for .NETのデザイナを利用して実現することもできます。デザイナを使えば.aspxの中にプロパティとして記述され、IDEでも一部を除いて表示フォーマットと同じ見た目で表示できます。サンプル「CZ0910FollowerType3」では、デザイナを使った設定にしています。

図5 サンプル「CZ0910FollowerType3」のIDEでの表示
図5 サンプル「CZ0910FollowerType3」のIDEでの表示

シートの設定

 プロパティウィンドウで、SPREAD for .NETのSheetsプロパティにあるボタンをクリックすると、SheetViewコレクションエディタが起動します。次のプロパティを設定します。

SheetViewコレクションエディタでの設定
AllowUserFormula False
AutoGenerateColumn False
ColumnCount 9
DataAutoCellTypes False
OperationMode ReadOnly
ReferenceStyle R1C1
図6 SheetViewコレクションエディタ
図6 SheetViewコレクションエディタ

列の設定

 列の設定はSPREADデザイナからサイドメニューの「セル」を選びます。

図7 SPREADデザイナ
図7 SPREADデザイナ

 「セル」は、列ヘッダをクリックして列を選択すれば列の設定プロパティ、行ヘッダをクリックして行を選択すれば行のプロパティ、セルを範囲指定すればセルのプロパティが設定できます。

 また、Formulaプロパティに数式を設定するときも、数式エディタを使えば数式の正当性がチェックできるため、修正と実行を繰り返して数式を探る必要がなくなります。

図8 数式エディタ
図8 数式エディタ

 SheetViewコレクションエディタからはシートスキンエディタも表示可能なので、スキンを切り替えながら好みのデザインを探せるので便利です。

図9 シートスキンエディタ
図9 シートスキンエディタ

コードの追加

 型付きデータセットをDataSourceプロパティに指定してあれば、SPREADデザイナの中でDataFieldプロパティを設定できますが、今回のサンプル「CZ0910FollowerType3」は型付きデータセットではないため、ページロードで設定する必要がありますが、サンプル「CZ0910FollowerType2」よりもコード量は少なくなっています。

 また、OnPreRenderイベントにてサンプル「CZ0910FollowerType2」と同様に、再計算と画像表示のコードの記述が必要です。

リスト13 ページロード時の追加処理
Private Sub Me_Load()
    'スタイル設定用CSSを自動生成して使用する
    Me.FpSpread1.RenderCSSClass = True
    '行高/列幅を変更できないようにする
    Me.FpSpread1.ActiveSheetView.RowHeader.Rows.Default.Resizable = False
    Me.FpSpread1.ActiveSheetView.ColumnHeader.Columns.Default.Resizable = False
    '列の定義を行う
    With block
        'ID列は非表示にする
        Me.FpSpread1.ActiveSheetView.Columns(0).DataField = "ID"
        Me.FpSpread1.ActiveSheetView.Columns(0).Visible = False
        '名前列の設定を行う
        Me.FpSpread1.ActiveSheetView.Columns(2).DataField = "Name"
        'ID名列の設定を行う
        Me.FpSpread1.ActiveSheetView.Columns(3).DataField = "ScreenName"
        'プロテクション列は非表示にする
        Me.FpSpread1.ActiveSheetView.Columns(4).DataField = "IsProtected"
        Me.FpSpread1.ActiveSheetView.Columns(4).Visible = False
        'フォロー列は非表示にする
        Me.FpSpread1.ActiveSheetView.Columns(6).DataField = "IsFollowing"
        Me.FpSpread1.ActiveSheetView.Columns(6).Visible = False
        '最新の発言列の設定を行う
        Me.FpSpread1.ActiveSheetView.Columns(8).DataField = "StatusText"
    End With
End Sub

 .NET標準のRepeaterコントロールを使った場合、HTMLで作成した1行分の表示を確認するのにも、実行する必要があります。多少のコーディングは必要ですがSPREADデザイナを使う事で実行せずにデザインを確認しながら見た目を調整できるデザイナの存在は開発の現場では“心強い”のひとことにつきます。

まとめ

 SPREAD for .NET Web Forms Ed.は、HTMLやCSSに詳しくない人でもSPREADエディタを使って綺麗な一覧表を作成できます。また、編集中でもデザインが確認できるのも便利です。

 HTMLにはtableタグがあるため、Webアプリケーションで一覧表は簡単に作れそうですが、さまざまな要件を満たし、デザイン的にも使いやすいものを作ろうとすると一気に難易度が上がります。この上がった難易度を、また強制的に下げてくれるのがSPREAD for .NET Web Forms Ed.と言えるでしょう。

製品情報

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 初音玲(ハツネアキラ)

     国内SIerのSEでパッケージ製品開発を主に行っており、最近は、空間認識や音声認識などを応用した製品を手掛けています。  個人的には、仕事の内容をさらに拡張したHoloLensなどのMRを中心に活動しています。  Microsoft MVP for Windows Development...

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5