CSVデータがあればExcel形式で一覧表示したくなる気持ち

データを可視化するお話です。
モバイルアプリ用コンポーネントのXuni(ズーニー)は、データ可視化を目的としたコントロールです。データをモバイルアプリ上で表現するために、グリッドやチャートを提供しています。
表示するためには、必ず何らかの手段でデータを引き渡す必要があります。

こちらの記事ではJSON形式のデータをFlexGridを利用してグリッドビューを表示する例を解説しました。 

今回はCSV形式のデータをもとに一覧表を作成します。
利用するのは日本郵便株式会社が提供している郵便番号データです。 CSV形式のファイルで提供されており、同社のWebサイトからダウンロードできます。

郵便番号データダウンロード – 日本郵便

使う前に郵便番号データの説明を見ると、全国版は12万件もあるとのことでした。今回はテストデータで利用するので、グレープシティ本社の郵便番号[981-3205]が含まれる宮城県版を利用します。

そこにデータがあるから

データがあれば、まずはExcelのような一覧表示をしたくなります。
見やすく可視化するためには必要な手続きです。
ダウンロードしたファイルはCSV形式ですので、Excelで読み込めば簡単に表示できます。
しかし、それでは単純なので手法を変え、Visual Studio Code(以下、VSCode)を利用してデータを表示します。

VSCodeは一般利用が可能なエディタなので、CSVファイルを読み込んでもそのまま表示され、Excelのような表示にはなりません。これはメモ帳などの他エディタと同じです。
ちなみにこの記事もVSCodeで書いています。

Excel形式で表示する拡張機能

VSCodeには拡張機能(エクステンション)を利用する仕組みが備わっており、拡張機能は自由に作成して利用でき、公開すれば他の人も利用できます。
グレープシティが公開しているVSCode用の拡張機能「Excel Viewer」はその名の通り、Excelファイルを参照可能にするエクステンションです。

VSCodeからMarketplaceに接続すれば、簡単にインストールできます。
検索して追加するだけですので詳細な手順は割愛します。

f:id:ComponentOne_JP:20170209120235p:plain

拡張機能を利用するにはVSCodeを起動した状態で、コマンドパレットを開きます。 コマンドパレットはメニューからも開きますが、Windowsであれば「Ctrl+Shift+”P”」、macOSであれば「⌘+shift+”P”」のショートカットが利用可能です。

実は、拡張機能のインストールもコマンドパレットから実行できます。
Excel Viewerは
ext install gc-excelviewer
を実行し、VSCodeを再起動することで利用可能です。

CSVファイルを表示

それでは実際に利用してみます。
CSVファイルをExcel形式で表示するには、まず通常通りVSCodeでファイルを開きます。
[ファイル]-[開く]から対象ファイル「04MIYAGI.CSV」を選択してください。
ファイルを開くと文字コードが異なるので文字化けします。
これを正しいエンコード(Shift-JIS)で再度読み込むには、ウィンドウの右下にエンコード表示(この時点ではUTF-8)を押すと、「エンコード付きで再読み込み」を実行するコマンドパレットが開くので処理を選択します。
次にエンコードJapanese(Shift-JIS)を選択すると、ファイルが再読み込みされて日本語が正しく表示されました。

f:id:ComponentOne_JP:20170209120056p:plain

CSVで表示された状態から、前述の手法でコマンドパレットを開きます。 コマンド入力エリアにCSV: Open Previewと入力してください。実際は途中で補完され候補が表示されるので、該当する処理してEnterを押します。

f:id:ComponentOne_JP:20170209131807p:plain

すると別のタブが起動し、CSVファイルがExcel形式でプレビュー表示されます。 今回のファイルはヘッダーがないので、最初のデータがヘッダーとして扱われています。
プレビュー表示された画面では、Excelのようにヘッダー部分をクリックすることでソートが可能です。あくまでビューですので元データに変更はなく編集もできませんが、データを一通り見やすい形で確認することはできます。
Excel ViewerはmacOS版のVisual Studio Codeでも同様に利用可能です。

f:id:ComponentOne_JP:20170209120124p:plain


モバイルアプリで一覧表示する

ここからがXuni(ズーニー)のお話です。
Xamarin.Formsを利用し、C#でAndroid、iOSのサンプルアプリを作成します。
前項で確認した郵便番号データをを表示するアプリです。 手順は以下になります。

1.  Xamarin.Formsのプロジェクトを作成
2.  Xuniを利用する設定
3.  データをプロジェクトに組み込む
4.  データを読み込むクラスを作成
5.  表示する画面の設定

1と2の説明は省略します。すでにXuniの利用準備が整っているプロジェクトを公開していますので、これを改造して利用します。プロジェクトは以下からダウンロード可能です。

データをプロジェクトに組み込む

ダウンロードしたプロジェクトをVisual StudioまたはXamarin Studioで開きます。
読み込むためのCSVファイル「04MIYAGI.CSV」はPCLプロジェクトの配下に保存します。 ここでは「Xuni_QuickStart」プロジェクトの直下に、既存ファイルとして追加します。 追加したファイルのプロパティページを開き、以下の設定を行います。
ビルドアクション:EmbeddedResource
そして読み込み時に利用するリソースIDをメモしておきます。
Xuni_QuickStart.Postal_04MIYAGI.csv

データモデルを作成

データモデルのクラスを作成します。データ構造を定義し、読み込んだCSVファイルからList型のデータセットを作成します。 リソースからデータを読み込む際には、メモしておいたリソースIDを指定します。

// 郵便番号データのモデル
public class PostalCodeModel
{
public String ID { get; set; }      // ID
public String ZIP { get; set; }    // 郵便番号の上3桁
public String Postal7 { get; set; }  // 7桁の郵便番号
public String Pref { get; set; }   // 都道府県
public String City { get; set; }   // 市区町村
public String Town { get; set; }   // 地番
public PostalCodeModel()
{
}
public static List<PostalCodeModel> getPostalCodeList()
{
var _postalCodeList = new List<PostalCodeModel>();  //リストを作成
var assembly = typeof(PostalCodeModel).GetTypeInfo().Assembly;
//データファイルからデータを読み込み
Stream stream = assembly.GetManifestResourceStream("Xuni_QuickStart.Postal_04MIYAGI.csv");
using (var sr = new System.IO.StreamReader(stream))
{
int count = 1;
while (!sr.EndOfStream)
{
//1行ずつ読み込む
var sn = sr.ReadLine().Split(',');
if (sn.Length > 1 && sn[0].Trim().Length > 0)
{
var data = new PostalCodeModel();
data.ID = sn[0].ToString();
//郵便番号データを格納
data.ZIP = sn[1].ToString();
// 数値データを郵便番号形式にフォーマット
data.Postal7 = String.Format("{0:000-0000}", int.Parse(sn[2].ToString()));
data.Pref = sn[3].ToString();
data.City = sn[4].ToString();
data.Town = sn[5].ToString();
_postalCodeList.Add(data); //データをリストに追加
count++;
}
}
}
return _postalCodeList;
}
}
ビューモデルを作成

データをビューであるFlexGridに表示するための、ViewModelを作成します。 ViewModelの内部で、データモデルから郵便番号データを読み込んだListを取得し、 FlexGridのItemsSourceに接続するプロパティにセットします。

// 郵便番号データのビューモデル- FlexGridのBindingContextに設定 
public class PostalCodeViewModel
{
public PostalCodeViewModel()
{
}
// データセットを返すプロパティ-FlexGridのItemsSourceに接続
public List<PostalCodeModel> PostalCodeList
{
// データモデルから郵便番号リストを取得
get { return PostalCodeModel.getPostalCodeList();}
}
}
ビューを作成

最後にデータを表示するFlexGridを配置したビューを作成します。プロジェクトにあらかじめ作成済みのサンプルページには必要な設定が完了していますので、一部を変更するだけです。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Class="Xuni_QuickStart.Xuni_QuickStartPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Xuni_QuickStart"
xmlns:xuni="clr-namespace:Xuni.Forms.FlexGrid;assembly=Xuni.Forms.FlexGrid"
Padding="0,20,0,0">
<Grid VerticalOptions="FillAndExpand">
<xuni:FlexGrid x:Name="grid" ItemsSource="{Binding PostalCodeList}"/>
</Grid>
</ContentPage>
コードビハインドの記述

ビューのコードビハインドにFlexGridの設定を追加します。
FlexGridとビューモデルを接続するために、BindingContextに設定します。 また、FlexGridの設定をデータを表示する各列を定義します。コード全体は以下です。
これで、FlexGridに渡されたデータソースを表示できるようになります。

public Xuni_QuickStartPage()
{
InitializeComponent();
// ViewModelをBindingContextに設定
grid.BindingContext = new PostalCodeViewModel();
// 先頭の2列は非表示
grid.Columns[0].IsVisible = false;
grid.Columns[1].IsVisible = false;
// FlexGridに表示する列のヘッダーを指定
grid.Columns[2].Header = "郵便番号";
grid.Columns[3].Header = "都道府県";
grid.Columns[4].Header = "市区町村";
grid.Columns[5].Header = "地番";
// 列幅を比率で指定するスターサイズ機能
grid.Columns[2].Width =  new GridLength(1,GridUnitType.Star);
grid.Columns[3].Width = new GridLength(1.5, GridUnitType.Star);
grid.Columns[4].Width = new GridLength(1.5, GridUnitType.Star);
grid.Columns[5].Width = new GridLength(2, GridUnitType.Star);
// 列ヘッダーのみを表示する
grid.HeadersVisibility = Xuni.Forms.FlexGrid.GridHeadersVisibility.Column;
}
iOSの設定

iOSアプリでは、Xuniの初期化処理を追加する必要があります。
iOSプロジェクトのAppDelegate.csを開いて、FinishedLaunchingメソッドに以下のようにコードを追加してください。

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
// Xuniのコンポーネントを初期化
Xuni.Forms.FlexGrid.Platform.iOS.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}

これはXamarin.Formsのカスタムコントロールでは、必要になる手続きです。
他のXuniコントロールや他のカスタムコントロールでも同様になります。Androidでは不要です。

完成

以上で準備が整いました。実行すると郵便番号一覧を表示します。
FlexGridの基本機能にソートがあるので、前述のVSCode同様にヘッダー部分をタップするとソートができます。 f:id:ComponentOne_JP:20170209120141p:plain

まとめ

今回データグリッドを表示したXuniのコントロールはFlexGridです。
その前に紹介した「Excel Viewer」は、JavaScriptライブラリ製品Wijmo(ウィジモ)のFlexGridを利用して開発しています。
データがあるならExcel形式で表示という要望に応えるために、多種多様なプラットフォームでFlexGridを揃えています。

FlexGrid (フレックスグリッド)
FlexGrid for WPF – ComponentOne Studio(コンポーネントワンスタジオ)
FlexGrid for WinForms – ComponentOne Studio
FlexGrid for UWP – ComponentOne Studio
FlexGrid for ASP.NET MVC – ComponentOne Studio
FlexGrid for Silverlight – ComponentOne Studio
FlexGrid – JavaScript/TypeScript/Angular – Wijmo(ウィジモ)
FlexGrid – Xamarin/Android/iOS – Xuni(ズーニー)

追記:この記事で紹介している「Xuni(ズーニー)」は、2017年7月に提供を終了し、新たに「ComponentOne Studio for Xamarin」として提供しています。

追記:ComponentOne for XamarinのFlexGridでCSVデータを取り扱っている記事はこちらです。