【一般】Excelでのデータ管理をデータベースでのデータ管理に移行してみる

## はじめに ##
現在、Microsoft Excelを利用したデータの管理を行っているケースが、まだまだ多いのではないでしょうか。 
大小を問わずまだまだ多くの企業では、日々の仕事の煩雑に追われ、慣れ親しんだExcelを利用したデータの入力および管理から抜けられずにいるのではないでしょうか。
そうして日々蓄積されたデータには、会社営業の行く先を決める大事な情報がたくさん入っていると思われますが、複数のExcelファイルに分かれたデータからそのような大事な情報を読み出すには、それなりの労力と時間を費やす必要があると思われます。
一般的には、データは社内ネットワーク上に配置されたデータベースサーバーに集積され共有されることで、社内の各部署からそれぞれに必要なデータが常に閲覧可能になり、迅速な意思決定の助けになればいいですよね。

今回は、[Sharperlight](https://sharperlight.jp/)を利用して、それを実現する第一歩を見ていきたいと思います。
ここに、このようなExcelで作成された売上台帳があるとします。このサンプルを利用して実際に作業してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b4b17398-e4a1-1ab8-6cf3-63a6a1317139.png)

## データベースの準備 ##
Excelで作成された売上台帳のデータを、Microsoft SQL Serverデータベースに保存する準備を行います。
### 空データベース ###
MS SQL Server Management Studioを利用して、データ保存用のデータベースを新規作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0a25be1d-13ce-9540-c001-6decec112687.png)
### テーブル ###
作成したデータベースに、新しいテーブルを準備します。
Excelの売上台帳を注意深く読んでみます。
どうやらヘッダーとその詳細に分かれそうですね。
伝票番号306で見てみると、緑の列がヘッダー情報で、赤の列がその明細のようですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/aa45c6b3-1c48-4211-a893-adc76c9f4e4d.png)
では、`ヘッダーテーブル`と`明細テーブル`を作成します。
Excelシート上の列名を利用します。
```
--売上ヘッダーテーブル
USE [〇〇会社]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[SalesHeader](
	[Row_ID] [int] IDENTITY(1,1) NOT NULL,
	[伝票番号] [int] NOT NULL,
	[伝票単位数] [int] NOT NULL,
	[売上区分] [nvarchar](100) NOT NULL,
	[年月日] [date] NOT NULL,
	[担当営業員] [int] NOT NULL,
	[店舗支店コード] [nvarchar](50) NOT NULL,
	[顧客コード] [nvarchar](50) NOT NULL,
	[顧客名] [nvarchar](200) NOT NULL,
	[顧客TEL] [nvarchar](50) NOT NULL,
	[メールアドレス] [nvarchar](200) NOT NULL,
 CONSTRAINT [PK_dbo_SalesHeader_Row_ID] PRIMARY KEY CLUSTERED 
(
	[Row_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
```
```
--売上明細テーブル
USE [〇〇会社]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[SalesDetail](
	[Row_ID] [int] IDENTITY(1,1) NOT NULL,
	[伝票番号] [int] NOT NULL,
	[明細番号] [int] NOT NULL,
	[商品コード] [nvarchar](50) NOT NULL,
	[数量] [int] NOT NULL,
	[単位] [nvarchar](20) NOT NULL,
	[単価] [int] NOT NULL,
	[金額] [int] NOT NULL,
	[分類] [nvarchar](10) NOT NULL,
	[品番] [nvarchar](100) NOT NULL,
 CONSTRAINT [PK_dbo_SalesDetail_Row_ID] PRIMARY KEY CLUSTERED 
(
	[Row_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f9ea9d42-73d2-19c7-7b7a-854e8274466f.png)
これで、売上データの入れ物は準備できました。

## Sharperlight データモデルの作成 ##
ここでは、Sharperlightを使用するための準備をします。
Sharperlightとデータベースの会話を成立させるためのコネクター: **データモデル**を作成します。
データモデルの作成はSharperlightスタジオで行います。Sharperlightアプリケーションメニューから**スタジオ**を起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/04cceb80-a928-5f2a-3754-54dccaa2516b.png)
### 接続 ###
Sharperlightスタジオとデータベースを接続し、会話に必要なデータベーススキーマを読み込みます。
メニューバーから`New`アイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/2d167a42-6d03-a4ee-d1df-aa706cb03a41.png)
データモデル（ここではプロダクトと呼ぶ）に必要な情報を入力します。`OK`で先に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/103a3bea-d35c-6e01-f3fe-6f625a54a659.png)
データベースの接続を確立します。
先ほど作成したデータベースの接続情報を入力します。`接続`テストボタンで接続を確認します。上手く接続ができたら`OK`ボタンで先に進みます。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a1426c4a-c940-b418-36a4-9b590232b9e2.png)
### スキーマ読込 ###
スキーマを読み込みますかという確認メッセージが表示されるので、`Yes`ボタンで先に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3abe331c-d233-4278-56fb-03900c7f5b81.png)
スキーマを読み込むためのダイアログが表示されます。`Get Tables`ボタンで読み込みを開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/be66d97e-9816-f6e9-1cd9-96535d728f07.png)
スキーマ情報が表示されたら`OK`ボタンで読み込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f77939a3-8873-d0ae-a685-d878bfa73813.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/c35b2cdf-5d2b-b9bb-0184-029bd48a3cea.png)
スキーマが読み込まれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0eaffb11-b472-15d9-acf4-1ab4c543bbce.png)
### テーブル定義の編集 ###
既定ではこのデータモデルと対象データベース間の会話は**読み込み専用**となっています。
今回は、Excelファイルのデータをデータベースに書き込みたいので、テーブルの設定を**書き込み可**にします。
両テーブルの`Allow Table Writeback`オプションを**True**にします。テーブルのアイコンが赤くなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/ddd1b467-5654-57e7-69a6-e79624b8aa1d.png)
### データモデルの保存とSharperlightアプリケーション用の接続 ###
メニューバーの保存アイコンでデータモデルを保存します。
注意を促すメッセージが表示されるので、`OK`で先に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/637fa5ee-a56e-75aa-658b-e77853936e29.png)
既定の保存場所が指定されるので、`SAVE`ボタンで保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/48dcda21-3e26-706d-8d28-66f78606f0cf.png)
Sharperlightアプリケーション用の接続設定を促すメッセージが表示されるので、`Yes`ボタンで接続設定画面に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/ff2a0e72-1c04-45be-fcb9-91f7f7984ded.png)
Sharperlightクライアントセットアップが開きます。このアプリケーションでは、インストールされている各データモデルとその対象データベースの接続を管理します。
今回作成したデータモデルの対象データベースへの接続情報を入力し、`接続テスト`ボタンで接続を確認後、`OK`ボタンで先に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/ca0c9752-9fa1-a805-7017-0d57d2450a33.png)
以上でSharperlightデータモデルの作成は一応完了。Sharperlightスタジオを閉じます。

## データの書込み ##
では作成したデータモデルとその接続を利用してデータの書き込みを行います。
MS Excelを起動し、Sharperlightアドインにログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0dc1fc26-9f78-8e97-ad84-d4a3a6c479af.png)
そして売上台帳を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/c11613f8-61d6-4b04-b25b-aeac1e595552.png)
売上台帳がExcel上でのテーブル化がされていない場合は、テーブル化しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/85ed4c00-f0b5-e916-445c-bfa1f0c79030.png)
### Sharperlight Writeback(書き戻し)の定義 ###
データの書き込みには、SharperlightのWriteback(書き戻し)機能を利用します。
Sharperlightリボンの`書き戻し`アイコンをクリックして`書き戻し`ダイアログを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6301584e-9d9f-f960-fdd2-6cfb36485f2e.png)
#### 製品の選択 ####
製品（データモデル）を指定します。検索ボタンで一覧から選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cc180f5e-cc17-57a5-dd6c-b6335667f0fa.png)
#### テーブルの選択 ####
検索ボタンでをクリックすると、選択した製品（データモデル）内で書き込み可なテーブルの一覧が表示されるので、その中から書き込み対象となるテーブルを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a15f02ed-269e-7267-a50d-7e0e24d163f8.png)
フィールドタブに書き込み対象のフィールド一覧が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b22ea25e-a033-3d48-e216-d833d3007ba4.png)
#### 書き戻し名の記入 ####
この書き戻し定義を保存する場合の`保存名`となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/2b2a9690-8ca9-a15e-460f-410d3e94bad6.png)
#### フィールドのマッピング ####
Excelシート上の列とデータベーステーブルの列をデータモデルを介して結びつけます。
フィールドタブ上のどのフィールドでもよいので選択します。その後Excelシート上のテーブルヘッダーをダブルクリックします。マッピング機能が起動し、注意を促すメッセージが表示されます。`Yes`ボタンで確定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8a778358-61f5-a672-10a6-57f6b7dbd1b5.png)
Excelシート上の列名とデータモデルに定義された列名が同じ場合、この機能でマッピングが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/9ea4eaac-0a7c-8144-2cdf-6e48837262ac.png)
**店舗支店コード**と**顧客 Tel**フィールドのマッピングが完了していません。これは列名の不一致によるものです。手動でマッピングを行います。
フィールドタブ上の**店舗支店コード**を選択した後、Excelシート上の店舗支店コード列のヘッダーをダブルクリックします。先ほどと同じメッセージが表示されるので、今度は`No`ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/58b6bf3f-610e-3a82-2cfd-78fe2d1bc03b.png)
このようにマッピングが設定されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8cb5d7fb-01e1-63e9-dc53-dd77e7635a16.png)
同じように**顧客 Tel**フィールドにも手動でマッピングを作成します。
このようにマッピングが完了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/28b0ec34-ea47-97c5-6f56-eac923ec5f68.png)
#### ドライバ列の指定 ####
Excelシートからデータを読む場合、どの列を基準にするかを指定します。
`伝票番号`列をドライバとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a991297e-4815-37e7-b856-5cee69008519.png)
#### Writeback(書き戻し)の定義の検証 ####
定義が完了したので動作の検証を行います。`検証`ボタンをクリックします。このようなメッセージが表示されれば正常です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/033f16d6-aa77-1935-65da-646f8af0a28b.png)
#### Writeback(書き戻し)の定義の保存 ####
ダイアログを閉じると保存を促すメッセージが表示されるので、`Yes`ボタンで保存します。上記で記入した`書き戻し名`でこのシート内に保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d29e8ce5-234d-da91-68b1-7a7905be35dc.png)
### Sharperlight Writeback(書き戻し)の実行 ###
では早速実行してみます。Sharperlightリボンの書き戻しアイコンで書き戻しダイアログを再度開き、書き戻し名検索ボタンで保存されている書き戻し定義一覧を表示します。読み出したい定義`売上ヘッダー`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f77a77ac-7732-6c42-ba3d-c37a7fb97bdc.png)
定義が読み込まれたら`実行`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/2da35d70-bf85-722e-ec99-1ca152b4b0a1.png)
このようなログが表示されれば、実行は正常に行われたということです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a547ef37-6e44-76db-9173-bda8afae007c.png)
データベーステーブルを確認してみます。
おやおや！書き戻しは正常に行われているのに、ヘッダー情報が重複してしまっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/53e65c2d-4227-a453-44de-7eab6faa55d4.png)
調整の必要がありますね。
### ユニークキーの設定 ###
データモデル側でユニークキーの設定を行います。
Sharperlightスタジオで**〇〇会社営業データ**データモデルを開きます。
テーブルタブのSalesHeaderテーブルの定義を開きます。
`伝票番号`フィールドの`Is Unique`オプションを**True**にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/31265753-4e0e-23e8-76bb-8d2890cb7a45.png)
データモデルを保存します。変更を有効にするためExcelアドインからログオフし、再度ログオンします。
Truncate tableコマンドでデータベーステーブルを空っぽにして、再度書き戻しを実行します。
書き戻しは正常終了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1a6e6fbf-5344-9338-a205-b6c4c6df5e1c.png)
データベーステーブル側では、重複は解決されたようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3f923d70-d743-e936-d22e-1f3b3206dc9a.png)
正確に確認してみましょう。
```
SELECT 伝票番号, COUNT(伝票番号)
FROM [〇〇会社].[dbo].[SalesHeader]
GROUP BY 伝票番号
HAVING COUNT(伝票番号) > 1
```
重複はありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d14fd394-74f8-bba5-170a-5c4b2a62df52.png)

同じような手順でSalesDetailテーブルもデータの書き戻しを行います。
SalesDetailテーブルでも同じように重複問題が発生すると思われるので、データモデルのテーブル定義を更新してから書き戻しを実行します。
SalesDetailテーブルでは、伝票番号、明細番号および商品コードでユニークキーを形成します。
このように設定しデータモデルを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/fc408c32-7b73-5500-ee67-027fb847525a.png)
あとはSalesHeaderテーブルの時と同じように書き戻し定義を作成し実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/47683adf-28c8-5059-fd83-838c2763e9be.png)
### Excel売上台帳を書き戻し専用シートにする ###
ここまでで基本となる書き戻し定義の作成が完了し、Excel売上台帳上のデータがデータベースに書き戻されたので、そのデータを元にExcel売上台帳を書き戻し専用シートに改良します。
以下の手順の繰り返しで、売上データの入力管理が行えるようにします。
 1. クエリを利用してデータベースとExcel売上台帳のデータの同期をとる。
 2. 新規データをExcel売上台帳に入力する。
 3. Excel売上台帳の書き戻し定義を利用して、データベースを更新する。

`改良する前にExcel売上台帳のバックアップをとっておきます。`
#### クエリの定義 ####
クエリを作成する前にデータモデルのSalesDetailテーブル定義にテーブルJOINを追加しておきます。クエリを作成する場合、何かと便利なのでJOINを作成しておきます。
これは、実際のデータベースに作成するわけではなく、Sharperlightのデータモデル上に作成されるJOINです。
`伝票番号`フィールドを選択し、右クリックメニューから**New Join**をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3d019149-9a91-fac2-f6f7-a5bea9f54786.png)
JOIN作成支援ダイアログが表示されるので、SalesHeaderテーブルへのJOINを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/09ca1dd7-2899-b2da-14bc-dab84becdf55.png)
テーブルJOINが作成されました。データモデルを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/899999dc-d8d7-4531-44cc-043a5db90813.png)
Excel売上台帳に戻り、データモデルへの変更を有効にするためにSharperlightからログオフし、再度ログオンします。
行を最上段に追加します。セルA1を選択後、Sharperlightリボンからテーブルアイコンをクリックしクエリビルダを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/39552cf7-da6f-324e-bd68-b598823c950c.png)
クエリビルダでは下図のような設定を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/56ee9e08-2e92-c6d6-1e4c-1eeaf48d48d2.png)
出力アイテムに設定したフィールドの説明をExcel売上台帳のテーブルヘッダー名に合わせておくといいでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/50c76991-68a7-d41f-d332-1da7c8e25a85.png)
クエリ名の入力を促すダイアログが表示されるので、クエリ名を入力しOKを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0a6dc609-0609-592d-9884-6cc2743cc26a.png)
Sharperlightテーブル式はセルA１に設定され、クエリが即実行されますが、結果は既存のExcelテーブルに邪魔されて表示されません。
シート上の既存のテーブルを削除します。既存のテーブルが削除されると直ぐSharperlightテーブル式が再度実行され、新たなテーブルが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/9a90c62d-48e7-16c6-12b1-73c4ad5cd606.png)
#### 書き戻し定義の更新 ####
クエリによってテーブルが再作成されたので、はじめに作成した書き戻し定義を見直します。
保存してある`売上ヘッダー書き戻し定義`を開き、すべてのマッピング情報を消去します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/bdfea289-db19-8b99-5956-d25ff01375df.png)
定義上の伝票番号を選択しExcelテーブルのヘッダーをダブルクリックします。新しいマッピングが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1991d179-cf2b-97a3-8f53-e2b05fe34501.png)
`閉じる`ボタンで保存します。
同じように`売上明細書き戻し定義`もマッピングを更新します。
### クエリとボタンの配置 ###
クエリ、二つの書き戻し処理がボタンで行えるようにします。
Excelシート上部に更に3行追加します。ここにボタンを配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6ae2b66c-8738-9ff8-91d8-a8d26915822f.png)
Sharperlightリボンより、**ボタン**->**再計算**->**mdRecalcActiveWorksheet**を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/bdb4433a-1674-ae52-7a44-afc8b7023402.png)
クエリを実行するボタンがこのように追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/34caed5a-f169-5d64-cc64-5ca8bea321cf.png)
セルA4にはクエリ式が定義されているので、行4は隠しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0023e44f-96b0-2267-660a-3bceeae8704c.png)
次に書き戻し定義を実行するボタンを追加します。
Sharperlightリボンより、**ボタン**->**書き戻し**->**mdWriteBack**を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/879f841c-c000-9c74-fce9-def232c25536.png)
書き戻し定義一覧が表示されるので、このボタンに結び付ける定義を選択すると書き戻しボタンが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/863c761c-979e-471a-1417-c86b209ac690.png)
最終的には、書き戻しボタンが二つできるのでキャプションを編集します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/46bb9eb3-5bd5-bc8b-3999-fe71752ddfd4.png)
こうすることで毎回書き戻し定義を呼び出して、書き戻し定義ダイアログ上の実行ボタンで実行する手間が省けます。
### 書き戻しログをシート上に表示する ###
最後に、書き戻しを実行した際に開かれるログ情報ダイアログが邪魔なので、ログ情報はシート上の指定の場所に表示するよう変更をかけます。
各書き戻し定義を開き、`処理オプション`タブに移動します。
履歴表示用のセルオプションにセル参照を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/e463e54a-0ede-582f-8e7c-e465c72219b1.png)
指定したシート上のセル属性を調整し、ログ情報が上手く表示されるようにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/e8609034-c801-32fa-e9bf-ba02c90b64a2.png)

以上で売上台帳を使用した書き戻しが可能になりました。
クエリでExcel売上台帳とデータベースの同期をとった後、新しい売上レコードを売上台帳に追加します。
次に`書き戻し:売上ヘッダー`ボタンで新しいレコードのヘッダー情報を先にデータベースに書き戻します。最後に`書き戻し:売上明細`ボタンで新しいレコードの明細情報をデータベースに書き戻します。
とりあえずこのような手順で日々の売上データをデータベースに書き戻すことができるようになりました。

## レポートの作成 ##
以上でExcel売上台帳上のデータがデータベースに移行できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/aa478f2c-0964-6ccf-52bf-ae2b2cae07e6.png)
あとはSharperlightを使用してデータの可視化をしてみます。
### レポート ###
もちろんSharperlight Excelアドインを利用して、Excel上にレポートを作成することも可能ですが、SharperlightパブリッシャーでWebレポートを作成し、Sharperlightサービスを利用して社内で共有することも可能です。また各種のセキュリティ設定を行った上で、外部に公開することさえ可能になります。
Sharperlightパブリッシャを起動します。`新規`ボタンで新しいレポートの作成を開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/eb1a05db-9dc2-19ca-4c45-9fc60971e8f8.png)
Webレポートのダイアログが開いたら、**コード**、**グループ**、**タイトル等**を記入し、`クエリを編集`ボタンでクエリの作成を開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d4beb8b3-76be-3cd4-58e3-91ca9c6918f0.png)
`モード`には**概要レポート**、`製品`には**〇〇会社営業データ**、`テーブル`には**Sales Detail**を指定します。
`選択`領域に選択可能なフィールド一覧が表示されるので、それらを利用して`フィルター`や`出力アイテム`を設定します。
`売上区分`フィールドと`年月日`フィールドにフィルターを設定してみました。`年月日`フィルターの値 **DATE -2m** は、Sharperlight特有の記号で、現在の年月日から2か月前(マイナス 2 month)という意味を表します。また年月日フィルターには、年/月オプションを設定し、年月単位でフィルターをかけるようにしました。
つまりクエリを実行する日が2023年5月の場合、生成されるWHERE句はこのようになります。
```
CAST(YEAR(J002.[年月日]) AS varchar(20)) + '/' + RIGHT('0' + CAST(MONTH(J002.[年月日]) AS varchar(20)),2) BETWEEN N'2023/03' AND N'2023/03'

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/34570848-c143-c18c-9b32-9ba047557e41.png)
では、`OK`ボタンでクエリを保存し、WEBレポートも`OK`ボタンで保存します。
Sharperlightサービスを起動し、早速作成したばかりのレポートをブラウザで開いてみましょう。以下のURLでレポートを表示できます。
```
http://localhost/DemoRest/Report/?query=QiitaSample.ExcelToDatabase
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/654ad0f9-b5d6-0d90-ad59-39148494a4ba.png)
もう少し編集してみます。
レポートのタイトルが左側に表示されるように編集します。`一般`タブの`配置オプション`で変更可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a1abd3c8-a5ae-5d10-d868-9680a1f07d09.png)
プロンプト（フィルター）を縦に揃えて（2行に渡って）表示します。`オプション`タブ、`プロンプトオプション`の`1行の項目`属性を**1**にします。**1行に1フィルターのみ表示**という意味で、今回はフィルターが2つあるので2行表示になるという事です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f80c2604-5937-a562-f778-b29e94aa074e.png)
では変更を保存して、ブラウザ上のレポートをF5で更新！どうでしょうか！？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/107fcf27-1ade-2c80-034f-eb88c1bbe9b6.png)
更に、伝票番号でグループ化してみます。
クエリを開いて、出力アイテムの伝票番号フィールドのオプションを編集します。
オプションダイアログの`並べ替えとグループ化`タブで伝票番号を指定し、`グループ化オプション` **基本**を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/52d8404d-6cf1-10e7-06e0-d9eabf14797d.png)
では変更を保存して、ブラウザ上のレポートをF5で更新！どうかな！？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3d27d396-3312-55ed-e9bd-17b0e35d2f2a.png)
### グラフ ###
売上伝票と返品伝票の推移をグラフで表示してみます。
新しいレポートを作成します。**コード**、**グループ**および**タイトル等**を記入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/7010a7ae-d38d-843e-6658-9567f5ad1b3d.png)
`クエリを編集`ボタンでクエリの作成を開始します。
先に作成したレポート同様、モード、製品、テーブル、いくつかのフィルターを設定し、出力アイテムも指定します。
今回は、フィルターに`売上区分`を**売上**用と**返品**用の二つ準備しました。これはこれから説明する出力アイテムに使用されます。
出力アイテムに先ず`売上日`を設定。更に`伝票番号`を二つ設定します。ひとつは、売上伝票をカウントするもの、もうひとつは、返品伝票をカウントするものです。それぞれの説明を、`売上伝票`と`返品伝票`と書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/50175218-aeee-2f08-2f4c-f729d61dbc93.png)
売上伝票をカウントする方のオプションでは、集計属性に**カウント**、出力項目にフィルターを適用属性では、先ほどの**売上区分：売上**フィルターを選択します。
返品伝票をカウントする方のオプションでは、`集計`属性に**カウント**、`出力項目にフィルターを適用`属性では、先ほどの**売上区分：返品**フィルターを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0c0d05bd-2cc2-9158-750c-18c6b2d46808.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/ef2af48f-f9d1-ea9d-e608-0d1e6116a7ec.png)
この設定でこのようなSQL文が生成されます。
```
,COUNT( CASE WHEN (J002.[売上区分]=N'売上'
) THEN J001.[伝票番号] ELSE NULL END )
,COUNT( CASE WHEN (J002.[売上区分]=N'返品'
) THEN J001.[伝票番号] ELSE NULL END )
```
ではプレビュー機能でクエリの確認。上手くデータが返ってきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/bed3fcb3-178d-bc22-7e5d-2e3fe0ccc912.png)
クエリを保存して、レポートダイアログに戻ります。
`オプション`タブで`既定の出力形式`を**Chart**に、更に`プロンプト`を無効にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0d4efb0f-501a-cf44-bdd4-b39c0f87a4f6.png)
`グラフ`タブでは、`グラフの種類`を**Area**、`サイズ：幅`を**1300**、`タイトルの回転-度`を**マイナス45度**、そして`カスタムタイトル`を**伝票数**とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cbd7c47d-3fcb-da07-9176-c9faa8676be7.png)
さあ、レポートを保存してブラウザで表示してみます。
```
http://localhost/DemoRest/Report/?query=QiitaSample.ExcelToDatabase2
```
このようなグラフが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6c18d960-6746-591d-edf5-5775a1443afa.png)
### ダッシュボードページ ###
Sharperlightダッシュボードページを使用して、先に作成した二つのレポートをタイル表示してみようと思います。
アプリケーションメニューから`ダッシュボードページ`を起動します。
新規ボタンで新しいダッシュボードページの作成を開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/94cd2a8d-6403-b82c-7e3f-87598c7c9e48.png)
ダッシュボードページ定義ダイアログが表示されます。
#### ダッシュボードページの詳細 ####
`一般`タブでは、このダッシュボードページの情報を記入します。**コード**、**グループ**および**タイトル**は最低限記入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/88e1ff83-c57f-2ed6-cf0e-c23c792797fe.png)
#### タイルの定義 ####
`タイル`タブでは、実際にタイルを定義していきます。
既定でタイルが４つ設定されていますが、今回は２つでいいので、`削除`アイコンで２つ削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/88eef1fe-033f-5e22-d430-5f9db0c88f14.png)
先ず一つめのタイルですが、`タイトル`には**売上伝票一覧**、コンテンツURLには、一番先に作成した通常レポートを指定します。右隣りの検索ボタンで検索することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8855f9ae-d0bd-851f-b030-e8b3e8e15c6a.png)
オプションの`タイトルを隠す`属性を**オン**にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d1cfc0fe-d7ea-98f5-49d0-b4c4787630b1.png)
後は`レイアウトの編集`エリアで大きさと位置を調整します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/205cc6b2-553a-883b-5a9f-4a40944523a1.png)
二つめのタイルも同じようにします。`タイトル`を**売上伝票と返品伝票の推移**、コンテンツURLには、先に作成したグラフレポートを指定します。指定したコンテンツURLの最後尾にグラフの幅を指定するオプション `&width=1000`を以下のように指定します
```
/Report?query=QiitaSample.ExcelToDatabase2&rtype=chart&ctype=area&width=1000
```
オプションの`タイトルを隠す`属性も**オン**にします。
最後に`レイアウトの編集`エリアで大きさと位置を調整します。
#### ダッシュボードページの検証と編集 ####
`ビュー`ボタンでダッシュボードページをブラウザに表示します。
最初はこのように一部が上手く表示されていない不完全なタイルが表示されると思われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3d623169-d1d0-daf8-3e38-714c897ceeda.png)
コンテンツが正しく見えるように、タイルの角を引っ張ってサイズを調整したり、タイル自体をドラッグして位置合わせを行います。
調整が終ったら、いづれかのタイルの右上隅に表示されるギアアイコンをクリックして、オプションページを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b628e892-3653-9785-b5f4-450acaf6a691.png)
オプションページが開いたら、`保存`ボタンで調整したサイズと位置を保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/84c58ff0-729a-8402-7703-942a139e1e17.png)
さて、どうかな？いい感じでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/2b6bc8c4-d05e-39a3-18e4-1562ef21565e.png)

## あとがき ##
長～い記事になってしまいましたが、この記事から何かひとつでも参考になるものが見つかって、あなたのお役に立てたらいいなと思います。